Статьи

ZooKeeper для регистрации и обнаружения микросервисов

В мире микросервисов несколько сервисов обычно распространяются в среде PaaS. Неизменяемая инфраструктура, например, предоставляемая контейнерами или неизменяемыми образами виртуальных машин. Услуги могут увеличиваться и уменьшаться на основе определенных предварительно определенных показателей. Точный адрес службы может быть неизвестен, пока служба не развернута и не готова к использованию.

Эта динамическая природа адреса конечной точки службы обрабатывается регистрацией и обнаружением службы. При этом каждая служба регистрируется у брокера и предоставляет более подробную информацию о себе, например адрес конечной точки. Другие потребительские сервисы затем запрашивают брокера, чтобы узнать местоположение сервиса и вызвать его. Существует несколько способов регистрации и запроса сервисов, таких как ZooKeeper, etcd, consul, Kubernetes, Netflix Eureka и других.

Рефакторинг от монолитного до микросервисного обслуживания показал, как выполнить рефакторинг существующего монолита в приложение на основе микросервиса. URI пользователя, каталога и сервиса заказа были определены статически. Этот блог покажет, как регистрировать и обнаруживать микросервисы с помощью ZooKeeper .

Большое спасибо Иоаннису Канеллосу ( @iocanel ) за все взломы ZooKeeper!

Что такое ZooKeeper?

ZooKeeper является проектом Apache и предоставляет распределенное, в конечном итоге согласованное хранилище иерархической конфигурации.

апач-Zookeeper-логотип ZooKeeper — это централизованный сервис для поддержки информации о конфигурации, наименования, предоставления распределенной синхронизации и предоставления групповых услуг. Все эти виды услуг в той или иной форме используются распределенными приложениями.

Apache ZooKeeper

Таким образом, служба может зарегистрироваться в ZooKeeper с использованием логического имени, а информация о конфигурации может содержать конечную точку URI. Он может состоять и из других деталей, таких как QoS.

Куратор-логотип У ZooKeeper есть крутая кривая обучения, как описано в Apache ZooKeeper Made Simpler with Curator . Таким образом, вместо непосредственного использования ZooKeeper в этом блоге будет использоваться Apache Curator .

Куратор n ˈkyoor͝ˌātər: хранитель или хранитель музея или другой коллекции — Хранитель ZooKeeper.

Apache куратор

Apache Curator имеет несколько компонентов, и этот блог будет использовать Framework :

Curator Framework — это высокоуровневый API, который значительно упрощает использование ZooKeeper. Он добавляет множество функций, основанных на ZooKeeper, и обрабатывает сложность управления соединениями с кластером ZooKeeper и повторных операций.

Apache Curator Framework

ZooKeeper Concepts

Обзор ZooKeeper предоставляет отличный обзор основных концепций. Вот некоторые из соответствующих:

  • Znodes : ZooKeeper хранит данные в общем иерархическом пространстве имен, которое организовано как стандартная файловая система. Пространство имен состоит из регистров данных — называемых znodes , на языке ZooKeeper — и они похожи на файлы и каталоги.
  • Имя узла : каждый узел в пространстве имен ZooKeeper идентифицируется путем. Точное имя узла — это последовательность элементов пути, разделенных косой чертой (/).
  • Клиент / сервер : клиенты подключаются к одному серверу ZooKeeper. Клиент поддерживает TCP-соединение, через которое он отправляет запросы, получает ответы, получает события наблюдения и отправляет удары сердца. Если TCP-соединение с сервером разрывается, клиент подключится к другому серверу.
  • Данные конфигурации : с каждым узлом в пространстве имен ZooKeeper могут быть связаны как данные, так и дочерние элементы. Изначально ZooKeeper был разработан для хранения координационных данных, поэтому данные, хранящиеся на каждом узле, обычно невелики (в диапазоне менее КБ).
  • Ансамбль : сам ZooKeeper предназначен для репликации на наборы хостов, называемых ансамблем. Серверы, которые составляют сервис ZooKeeper, должны знать друг о друге.

    zkservice

  • Часы : ZooKeeper поддерживает концепцию часов . Клиенты могут установить часы на znode. Часы будут срабатывать и удаляться при изменении znode.

ZooKeeper является системой CP относительно теоремы CAP. Это означает, что в случае сбоя раздела он будет согласованным, но недоступным. Это может привести к проблемам, которые объясняются в Eureka! Почему вы не должны использовать ZooKeeper для обнаружения сервисов .

Тем не менее, ZooKeeper — один из самых популярных механизмов обнаружения услуг, используемых в мире микросервисов.

Давайте начнем!

Запустить ZooKeeper

  1. Запустите экземпляр ZooKeeper в контейнере Docker:
    1
    docker run -d -p 2181:2181 fabric8/zookeeper
  2. Проверьте экземпляр ZooKeeper, используя telnet как:
    1
    telnet $(docker-machine ip dockerhost)

    Введите команду «ruok», чтобы убедиться, что сервер работает без ошибок. Сервер ответит «imok», если он работает:

    1
    2
    3
    4
    5
    Trying 192.168.99.103...
    Connected to dockerhost.
    Escape character is '^]'.
    ruok
    imokConnection closed by foreign host.

    В противном случае он не будет отвечать вообще. ZooKeeper имеет другие похожие четырехбуквенные команды.

Служба регистрации и обнаружения

Каждый сервис, Пользователь, Каталог и Заказ в нашем случае, имеет нетерпеливо инициализированный компонент, который регистрирует и отменяет регистрацию сервиса как часть методов инициализации жизненного цикла, как. Вот код из CatalogService :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
@Inject @ZooKeeperRegistry ServiceRegistry services;
 
private static final String endpointURI = "http://localhost:8080/catalog/resources/catalog";
private static final String serviceName = "catalog";
 
@PostConstruct
public void registerService() {
    services.registerService(serviceName, endpointURI);
}
 
@PreDestroy
public void unregisterService() {
    services.unregisterService(serviceName, endpointURI);
}

Код довольно прост, он внедряет класс @ZooKeeperRegistry квалификатором @ZooKeeperRegistry . Затем он используется для регистрации и отмены регистрации службы. Несколько URI, по одному для службы без сохранения состояния, могут быть зарегистрированы под одним логическим именем.

В это время квалификатор приходит из другого модуля maven. Более @ZooKeeperRegistry способ Java EE — переместить @ZooKeeperRegistry в расширение CDI ( # 20 ). И когда этот спецификатор при указании на любой конечной точке REST зарегистрирует сервис с ZooKeeper ( # 22 ). На данный момент URI конечной точки службы также жестко задан ( # 24 ).

Как выглядит класс ZooKeeper ?

  1. Класс ZooKeeper использует инжектор конструктора и ZooKeeper IP-адреса и порта ( # 23 ):
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @ApplicationScoped
    public class ZooKeeper implements ServiceRegistry {
     
        private final CuratorFramework curatorFramework;
        private final ConcurrentHashMap<String, String> uriToZnodePath;
         
        @Inject
        public ZooKeeper() {
            try {
                Properties props = new Properties();
                props.load(this.getClass().getResourceAsStream("/zookeeper.properties"));
                 
                curatorFramework = CuratorFrameworkFactory
                        .newClient(props.getProperty("host")
                                + ":"
                                + props.getProperty("port"), new RetryNTimes(5, 1000));
                curatorFramework.start();
                uriToZnodePath = new ConcurrentHashMap<>();
            } catch (IOException ex) {
                throw new RuntimeException(ex.getLocalizedMessage());
            }
        }

    Он выполняет следующие задачи:

    1. Загружает хост / порт ZooKeeper из файла свойств
    2. Инициализирует фреймворк куратора и запускает его
    3. Инициализирует хэш-карту для сохранения имени URI в сопоставлении zNode. Этот узел удаляется позже, чтобы отменить регистрацию службы.
  2. Регистрация сервиса осуществляется с помощью метода registerService :
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    String znode = "/services/" + name;
     
    if (curatorFramework.checkExists().forPath(znode) == null) {
        curatorFramework.create().creatingParentsIfNeeded().forPath(znode);
    }
     
    String znodePath = curatorFramework
            .create()
            .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
            .forPath(znode+"/_", uri.getBytes());
     
    uriToZnodePath.put(uri, znodePath);

    Код довольно прост:

    1. Создайте родительский zNode, если это необходимо
    2. Создать эфемерный и последовательный узел
    3. Добавить метаданные, включая URI, к этому узлу
  3. Обнаружение службы выполняется методом discover как:
    1
    2
    3
    4
    String znode = "/services/" + name;
     
    List<String> uris = curatorFramework.getChildren().forPath(znode);
    return new String(curatorFramework.getData().forPath(ZKPaths.makePath(znode, uris.get(0))));

    Опять же, простой код:

    1. Найти всех детей по пути, зарегистрированному для службы
    2. Получить метаданные, связанные с этим узлом, в нашем случае URI, и return. Первый такой узел возвращается в этом случае. Различные параметры QoS могут быть присоединены к данным конфигурации. Это позволит вернуть соответствующую конечную точку сервиса.

Читайте ZooKeeper Javadocs для API.

Часы ZooKeeper можно настроить для информирования клиента о жизненном цикле службы ( # 27 ). Кэши путей ZooKeeper могут обеспечить оптимизированную реализацию дочерних узлов ( # 28 ).

Несколько реализаций обнаружения сервисов

Наше приложение для корзины покупок имеет две реализации для обнаружения службServiceDisccoveryStatic и ServiceDiscoveryZooKeeper . В первом все статические URI определены статически, а во втором они извлекаются из ZooKeeper.

Другие способы регистрации и обнаружения могут быть легко добавлены путем создания нового пакета в модуле services и реализации интерфейса ServiceRegistry . Например, Snoop , etcd , Consul и Kubernetes . Не стесняйтесь отправить PR для любого из них.

Запустить приложение

  1. Убедитесь, что образ ZooKeeper работает, как описано ранее.
  2. Скачайте и запустите WildFly:
    1
    ./bin/standalone.sh
  3. Разверните приложение:
    1
    2
    cd microservice
    mvn install
  4. Доступ к приложению на локальном хосте: 8080 / everest-web / . Узнайте больше о приложении и различных компонентах в статье Рефакторинг от монолитных до микросервисов для приложений Java EE .

Наслаждайтесь!