Пример построения кластера консула и открытия сервиса Golang

задняя часть Go

Традиционные автономные приложения не очень динамичны, редко обновляются и переиздаются и редко автоматически масштабируются. Однако с популяризацией распределенных интернет-систем требования к масштабируемости и масштабируемости между сервисами также возрастают. Чтобы соответствовать вертикальному и горизонтальному расширению служб, в прошлом для настройки служб обычно использовались предварительно определенные порты.Когда новые службы должны быть подключены к сети или текущие службы нуждаются в избыточном расширении, нам необходимо статически «зарегистрировать» соответствующий IP-адрес. и информацию о порте в В одном месте информация синхронизируется через штатный метод "обновления" между программами, но с этим методом много проблем.Например когда нам нужно подключиться к мастеру Кафки, если меняется служебная информация , клиенту трудно узнать. Одним из простых и грубых способов является настройка файла hosts и использование предопределенного «доменного имени» в качестве основы для подключения к сервису, но это тоже хлопотно.При изменении сервиса файл hosts приходится менять вручную. относительно много услуг на сервере Down, сумма обслуживания просто ужас.

По сути, одним предложением: больше сервисов, больше проблем

Обнаружение службы не является панацеей. Если поставщик службы задач зависает, на самом деле сложно уведомить вызывающего абонента на 100% в режиме реального времени. Тем не менее необходимо повысить доступность службы в целом с помощью разумной архитектуры или методов аварийного восстановления.

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

В настоящее время основными компонентами обнаружения службы являются: consul, etcd, zookeeper, различия здесь не объясняются, и те, кто заинтересован, могут прочитать официальное введение консула:«Консул против ZooKeeper, doozerd и т. д.»

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

Архитектура Consul Service и основные концепции

На следующем рисунке показана архитектурная схема консула в измерении центра обработки данных.СЕРВЕР на рисунке — это кластер высокой доступности сервера консула, а КЛИЕНТ — это клиент консула. Клиент-консул не сохраняет данные, а клиент пересылает полученный запрос отвечающему серверу. Согласованность данных достигается между серверами через локальную или глобальную сеть. Каждый сервер или клиент является агентом-консулом, или сервер и клиент — это просто разные роли, которые играет агент.

consul-arch

(картинка взята с официального сайта)

Как видно из рисунка выше, консул использует протокол сплетен для управления членством и широковещательной рассылкой сообщений всему кластеру.

Консул использует два разных пула сплетен. Мы называем их LAN Gossip Pool или WAN Gossip Pool соответственно. Каждый центр обработки данных Consul (Datacenter) имеет пул сплетен в локальной сети, который содержит всех участников (сервер и клиент).

LAN Pool имеет следующие цели:

  • Членство позволяет клиентам автоматически обнаруживать серверные узлы, уменьшая объем требуемой конфигурации.

  • Распределенное обнаружение отказов позволяет выполнять работу по обнаружению отказов в нескольких точках сервера, а не централизованно на всех узлах всего кластера.

  • сплетни позволяют надежно и быстро транслировать события, такие как выборы лидеров

Пул WAN глобально уникален, независимо от того, к какому центру обработки данных он принадлежит, все серверы должны быть добавлены в пул WAN. Информация о членстве предоставляется пулом WAN, чтобы серверные узлы могли выполнять запросы между центрами обработки данных. Другими словами, этот пул отличается от пула LAN, и его цель — позволить центрам обработки данных обнаруживать друг друга с минимальным вмешательством. Когда сервер в центре обработки данных получает запрос из другого центра обработки данных, он может перенаправить запрос ведущему в центре обработки данных.

В каждом центре обработки данных клиенты и серверы смешаны. Обычно рекомендуется иметь 3-5 серверов. Это основано на компромиссе между доступностью и производительностью в случае сбоя, поскольку чем больше машин подключается, тем медленнее достигается консенсус. Однако количество клиентов не ограничено, их можно легко масштабировать до тысяч или десятков тысяч.

Консул кластерное здание

Подготовка окружающей среды

Чтобы изучить сервисы, предоставляемые Consul, для реализации регистрации и обнаружения сервисов, нам нужно установить тестовое кластерное решение для Consul Cluster.На самом деле создать кластер очень просто.Каждому серверу нужно только запустить команду консул агент, а потом разделить сервер и клиент по их ролям. Здесь наш план тестового развертывания представляет собой архитектуру с 3 серверами и 1 клиентом в центре обработки данных.

Чтобы продемонстрировать построение кластера, мы готовим четыре тестовых задания:

окрестности IP-адрес сервера имя узла Роль
centos 7.2 172.17.0.3 s1 server
centos 7.2 172.17.0.4 s2 server
centos 7.2 172.17.0.5 s3 server
centos 7.2 172.17.0.6 c1 client

Скачайте пакет консула на каждый сервер отдельно:

Консул, используемый в этом примере, имеет версию 1.1.0.

wget https://releases.hashicorp.com/consul/1.1.0/consul_1.1.0_linux_amd64.zip

unzip consul_1.1.0_linux_amd64.zip

После распаковки видно, что бинарный файл консула всего один, перемещаем его в директорию /usr/local/bin:

cp consul /usr/local/bin/

Затем проверьте, успешно ли установлен консул, выполнив команду:

consul -h

Usage: consul [--version] [--help] <command> [<args>]

Available commands are:
    agent          Runs a Consul agent
    catalog        Interact with the catalog
    event          Fire a new event
    exec           Executes a command on Consul nodes
    force-leave    Forces a member of the cluster to enter the "left" state
    info           Provides debugging information for operators.
    join           Tell Consul agent to join cluster
    keygen         Generates a new encryption key
    keyring        Manages gossip layer encryption keys
    kv             Interact with the key-value store
    leave          Gracefully leaves the Consul cluster and shuts down
    lock           Execute a command holding a lock
    maint          Controls node or service maintenance mode
    members        Lists the members of a Consul cluster
    monitor        Stream logs from a Consul agent
    operator       Provides cluster-level tools for Consul operators
    reload         Triggers the agent to reload configuration files
    rtt            Estimates network round trip time between nodes
    snapshot       Saves, restores and inspects snapshots of Consul server state
    validate       Validate config files/directories
    version        Prints the Consul version
    watch          Watch for changes in Consul

После установки консула на каждый тестовый сервер кластера мы можем начать сборку кластера.

s1 запускает службу консула:

Команда выполнения консула выглядит следующим образом:

consul agent -server -bootstrap-expect 1 -data-dir /data/consul/ -node=s1 -bind=172.17.0.3  -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0

В приведенной выше команде мы будем использовать несколько важных параметров:

  • сервер: укажите, что агент работает в режиме сервера, если это режим клиента, вам не нужно добавлять этот параметр.

  • bootstrap-expect: ожидаемое количество серверных узлов в центре обработки данных. Когда указано это значение, консул не будет загружать (запускать) весь кластер до тех пор, пока не будет достигнуто указанное количество серверов. Для тестовой демонстрации мы используем 1 здесь.

  • bind: Этот адрес используется для связи внутри кластера. Все узлы в кластере должны быть доступны по этому адресу. По умолчанию 0.0.0.0

  • node: имя узла в кластере, должно быть уникальным в кластере, по умолчанию используется имя хоста узла

  • rejoin: заставить консула игнорировать предыдущую процедуру выхода и по-прежнему пытаться присоединиться к кластеру после повторного запуска агента. То есть, если этот параметр не добавлен, после выхода текущего узла он не будет автоматически добавлен в кластер после следующего перезапуска, если он не будет запущен вручную.consul join xxxx, поэтому, чтобы уменьшить влияние на собственный сервис после перезапуска, здесь единообразно используется параметр -rejoin.

  • config-dir: Каталог файлов конфигурации.Файлы в нем единообразно оговорены, что файлы, оканчивающиеся на .json, будут автоматически загружаться и считывать регистрационную информацию службы.

  • клиент: адрес прослушивания службы консула.Узел агента консула в режиме клиента относительно прост и не имеет состояния и отвечает только за пересылку запросов на узел агента сервера.

Когда служба запускается, фоновый вывод похож на следующую информацию журнала:

$ consul agent -server -bootstrap-expect 1 -data-dir /data/consul/ -node=s1 -bind=172.17.0.3  -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0

BootstrapExpect is set to 1; this is the same as Bootstrap mode.
bootstrap = true: do not enable unless necessary
==> Starting Consul agent...
==> Consul agent running!
           Version: 'v1.1.0'
           Node ID: 'cccf0fec-2fd9-30d0-9105-8dd2ae6480d6'
         Node name: 's1'
        Datacenter: 'dc1' (Segment: '<all>')
            Server: true (Bootstrap: true)
       Client Addr: [0.0.0.0] (HTTP: 8500, HTTPS: -1, DNS: 8600)
      Cluster Addr: 172.17.0.3 (LAN: 8301, WAN: 8302)
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false

==> Log data will now stream in as it occurs:

    2018/05/31 03:54:36 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:cccf0fec-2fd9-30d0-9105-8dd2ae6480d6 Address:172.17.0.3:8300}]
    2018/05/31 03:54:36 [INFO] raft: Node at 172.17.0.3:8300 [Follower] entering Follower state (Leader: "")
    2018/05/31 03:54:36 [INFO] serf: EventMemberJoin: s1.dc1 172.17.0.3
    2018/05/31 03:54:36 [WARN] serf: Failed to re-join any previously known node
    2018/05/31 03:54:36 [INFO] serf: EventMemberJoin: s1 172.17.0.3
    2018/05/31 03:54:36 [WARN] serf: Failed to re-join any previously known node
    2018/05/31 03:54:36 [INFO] consul: Adding LAN server s1 (Addr: tcp/172.17.0.3:8300) (DC: dc1)
    2018/05/31 03:54:36 [INFO] consul: Handled member-join event for server "s1.dc1" in area "wan"
    2018/05/31 03:54:36 [INFO] agent: Started DNS server 0.0.0.0:8600 (udp)
    2018/05/31 03:54:36 [INFO] agent: Started DNS server 0.0.0.0:8600 (tcp)
    2018/05/31 03:54:36 [INFO] agent: Started HTTP server on [::]:8500 (tcp)
    2018/05/31 03:54:36 [INFO] agent: started state syncer
    2018/05/31 03:54:43 [ERR] agent: failed to sync remote state: No cluster leader
    2018/05/31 03:54:45 [WARN] raft: Heartbeat timeout from "" reached, starting election
    2018/05/31 03:54:45 [INFO] raft: Node at 172.17.0.3:8300 [Candidate] entering Candidate state in term 3
    2018/05/31 03:54:45 [INFO] raft: Election won. Tally: 1
    2018/05/31 03:54:45 [INFO] raft: Node at 172.17.0.3:8300 [Leader] entering Leader state
    2018/05/31 03:54:45 [INFO] consul: cluster leadership acquired
    2018/05/31 03:54:45 [INFO] consul: New leader elected: s1
    2018/05/31 03:54:45 [INFO] agent: Synced node info

Давайте проверим информацию о составе членов кластера:

$ consul members

[root@f147f8eb5593 /]# consul members
Node  Address          Status  Type    Build  Protocol  DC   Segment
s1    172.17.0.3:8301  alive   server  1.1.0  2         dc1  <all>

В выходных данных команды видно, что в текущем кластере есть только участник с именем s1, и его статус активен, что означает, что он работает нормально. dc1 — это имя центра обработки данных по умолчанию; Тип перечисляет роли участников, текущий сервер; в поле Адрес8301Этот порт является LAN-портом агента по умолчанию (WAN-порт по умолчанию 8300), протокол предназначен только для совместимости разных версий агента в консул-кластере, разные версии агента и протокола могут иметь разные значения, поэтому не будем это.

Давайте сначала вернемся к рабочему журналу, и мы найдем это предложение:

New leader elected: s1

Это показывает, что после запуска текущего кластера выборы также будут происходить, когда есть только один член, и s1 выбирается автоматически.

Для подтверждения мы можем использовать consul API для запроса информации о лидере для подтверждения:

curl http://localhost:8500/v1/status/leader

"172.17.0.3:8300"

Кромеconsul membersВ дополнение к команде вы также можете запросить информацию об участнике в кластере через официальный API (в настоящее время только один участник):

curl http://localhost:8500/v1/status/peers

["172.17.0.3:8300"]

Более подробную информацию о работе узла можно просмотреть с помощью команды consul info

После вышеописанной работы первый член нашего кластера считается развернутым, не останавливаемся, продолжаем добавлять в кластер разных участников :)

s2 запускает службу консула:

Подобно s1, команда выполнения консула s2 выглядит следующим образом:

consul agent -server  -data-dir /data/consul/ -node=s2 -bind=172.17.0.4  -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0

Когда мы закончим выполнение вышеуказанной команды, мы просмотрим информацию о кластере на машине s2:

//172.17.0.4 s2

$ consul members

Node  Address          Status  Type    Build  Protocol  DC   Segment
s2    172.17.0.4:8301  alive   server  1.1.0  2         dc1  <all>

В это время он показывает, что кластер, в котором находится s2, имеет только себя и не нашел s1, который мы запускали ранее.

Вернемся к s1, чтобы увидеть информацию об участнике:

//172.17.0.3 s1

$ consul members

Node  Address          Status  Type    Build  Protocol  DC   Segment
s1    172.17.0.3:8301  alive   server  1.1.0  2         dc1  <all>

Из вышеприведенного явления мы можем узнать, что после запуска s2 он автоматически не присоединяется к предыдущему кластеру.В настоящее время нам нужно вручную добавить консульский агент s2:

//172.17.0.4 s2

$ consul join 172.17.0.3

successfully joined cluster by contacting 1 nodes.

Таким образом, независимо от того, является ли это s1 или s2, когда мы снова проверяем информацию об участнике, обе стороны находят друг друга по отдельности.

$ consul members

Node  Address          Status  Type    Build  Protocol  DC   Segment
s1    172.17.0.3:8301  alive   server  1.1.0  2         dc1  <all>
s2    172.17.0.4:8301  alive   server  1.1.0  2         dc1  <all>

Помните параметр -rejoin нашей команды? Давайте посчитаем, будет ли он автоматически присоединяться к предыдущему кластеру, когда мы остановим и перезапустим s2

Мы выполняем следующие команды в s2:

//172.17.0.4 s2

$ consul leave

Graceful leave complete

Обратите внимание на информацию о члене s1:

$ consul members

Node  Address          Status  Type    Build  Protocol  DC   Segment
s1    172.17.0.3:8301  alive   server  1.1.0  2         dc1  <all>
s2    172.17.0.4:8301  left    server  1.1.0  2         dc1  <all>

В это время состояние s2 уже оффлайн (левый), и после того, как мы его перепишем "подтянем", лог s2 показывает:

2018/05/31 05:48:03 [INFO] serf: Attempting re-join to previously known node: s1.dc1: 172.17.0.3:8302
2018/05/31 05:48:03 [INFO] agent: Started DNS server 0.0.0.0:8600 (udp)
2018/05/31 05:48:03 [INFO] serf: Attempting re-join to previously known node: s1: 172.17.0.3:8301
2018/05/31 05:48:03 [INFO] consul: Adding LAN server s2 (Addr: tcp/172.17.0.4:8300) (DC: dc1)
2018/05/31 05:48:03 [INFO] agent: Started DNS server 0.0.0.0:8600 (tcp)
2018/05/31 05:48:03 [INFO] agent: Started HTTP server on [::]:8500 (tcp)
2018/05/31 05:48:03 [INFO] agent: started state syncer
2018/05/31 05:48:03 [INFO] serf: EventMemberJoin: s1.dc1 172.17.0.3
2018/05/31 05:48:03 [INFO] serf: Re-joined to previously known node: s1.dc1: 172.17.0.3:8302
2018/05/31 05:48:03 [INFO] serf: EventMemberJoin: s1 172.17.0.3
2018/05/31 05:48:03 [INFO] serf: Re-joined to previously known node: s1: 172.17.0.3:8301
2018/05/31 05:48:03 [INFO] consul: Adding LAN server s1 (Addr: tcp/172.17.0.3:8300) (DC: dc1)
2018/05/31 05:48:03 [INFO] consul: New leader elected: s1

... ...

После перезагрузки вы можете увидеть журнал ключей:

Re-joined to previously known node: s1: 172.17.0.3:8301

На первый взгляд узел может автоматически вернуться в предыдущий кластер.Далее давайте посмотрим на информацию об участнике:

$ consul members

Node  Address          Status  Type    Build  Protocol  DC   Segment
s1    172.17.0.3:8301  alive   server  1.1.0  2         dc1  <all>
s2    172.17.0.4:8301  alive   server  1.1.0  2         dc1  <all>

S2 действительно снова вернется в кластер, и эффект повторного присоединения будет достигнут.

s3 запускает службу консула:

Команда выполнения консула выглядит следующим образом:

 consul agent -server  -data-dir /data/consul/ -node=s3 -bind=172.17.0.5  -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0

Как и s2, при первом запуске не забудьте присоединиться к кластеру:

consul join 172.17.0.3

Подтвердить информацию об участнике:

$ consul members
Node  Address          Status  Type    Build  Protocol  DC   Segment
s1    172.17.0.3:8301  alive   server  1.1.0  2         dc1  <all>
s2    172.17.0.4:8301  alive   server  1.1.0  2         dc1  <all>
s3    172.17.0.5:8301  alive   server  1.1.0  2         dc1  <all>

На данный момент мы успешно запустили и запустили 3 сервера консула в нашем кластере.Далее давайте попробуем разные узлы роли.Мы пытаемся добавить клиентскую роль агента консула.

c1 запускает службу консула:

Команда выполнения консула выглядит следующим образом:

consul agent  -data-dir /data/consul/ -node=c1 -bind=172.17.0.6  -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0

Как и в случае с s2 и s3, при первом запуске не забудьте присоединиться к кластеру:

consul join 172.17.0.3

Просмотр информации о кластере:

$ consul members
Node  Address          Status  Type    Build  Protocol  DC   Segment
s1    172.17.0.3:8301  alive   server  1.1.0  2         dc1  <all>
s2    172.17.0.4:8301  alive   server  1.1.0  2         dc1  <all>
s3    172.17.0.5:8301  alive   server  1.1.0  2         dc1  <all>
c1    172.17.0.6:8301  alive   client  1.1.0  2         dc1  <default>

Поскольку в команде запуска c1 нет параметра -server, по умолчанию он будет работать в роли клиента.

Для полного теста попробуем еще раз протестировать консул-сервис, который отключает лидера (s1), а потом наблюдаем за запросом выборов

memberlist: Suspect s1 has failed, no acks received
2018/05/31 10:17:53 [INFO] memberlist: Suspect s1 has failed, no acks received
2018/05/31 10:17:54 [INFO] memberlist: Marking s1 as failed, suspect timeout reached (2 peer confirmations)
2018/05/31 10:17:54 [INFO] serf: EventMemberFailed: s1 172.17.0.3
2018/05/31 10:17:54 [INFO] consul: removing server s1 (Addr: tcp/172.17.0.3:8300) (DC: dc1)
2018/05/31 10:18:04 [INFO] consul: New leader elected: s3
2018/05/31 10:18:37 [INFO] serf: attempting reconnect to s1 172.17.0.3:8301
2018/05/31 10:19:07 [INFO] serf: attempting reconnect to s1 172.17.0.3:8301
curl http://localhost:8500/v1/status/leader

"172.17.0.5:8300"

Из приведенных выше журналов и информации возврата API после зависания s1 кластер выберет нового лидера как s3.

Таким образом, наше развертывание узла кластера и основная работа по тестированию в основном в порядке, и создать кластер с помощью consul довольно легко.

Пример обнаружения службы

Зарегистрировать тестовый сервис в консуле

Целью создания Consul Cluster является реализация регистрации и обнаружения сервисов.

Консул поддерживает два способа регистрации сервиса:

  • Зарегистрируйте HTTP API через службу Consul, и служба сама вызывает API для регистрации после запуска.

  • Зарегистрируйтесь, указав службу в файле конфигурации.

Документация Consul рекомендует использовать последний метод для настройки службы и регистрации службы, и конфигурация очень проста.Просто перейдите в каталог, указанный --config-dir в команде запуска, чтобы создать новый файл регистрации в формате json, например, например :

Зарегистрировать (развернуть) сервис на s3

//172.17.0.5 s3

touch /etc/consul.d/web.json

Затем заполните следующую регистрационную информацию (должна быть в стандартном формате Json)

{
  "service": {
    "name": "web",
    "tags": ["master"],
    "address": "172.17.0.5",
    "port": 9999,
    "checks": [
      {
        "http": "http://localhost:9999/health",
        "interval": "10s"
      }
    ]
  }
}

Эта конфигурация заключается в том, что мы настраиваем веб-службу на узле s3. В этой службе мы определяем имя, адрес, порт и т. д. службы, а также включаем конфигурацию проверок для проверки работоспособности. Приведенный выше пример будет выполняться каждый 10 секунд один разhttp://localhost:9999/healthзапросить как проверку работоспособности

Зарегистрировать (развернуть) сервис на c1

Аналогично регистрируем аналогичный веб-сервис и на c1:

//172.17.0.6 c1

touch /etc/consul.d/web.json

Заполните следующее

{
  "service": {
    "name": "web",
    "tags": ["master"],
    "address": "172.17.0.6",
    "port": 9999,
    "checks": [
      {
        "http": "http://localhost:9999/health",
        "interval": "10s"
      }
    ]
  }
}

После того, как и s3, и c1 создали файлы определения службы, нам нужно перезапустить агенты-консулы обоих, чтобы добиться эффекта обновления службы.

При запуске агентов-консулов ​​s3 и c1, наблюдая за лог-информацией, мы обнаруживаем, что оба они одновременно сообщают следующую информацию:

2018/05/31 06:50:02 [INFO] agent: Synced service "web"
2018/05/31 06:50:03 [WARN] agent: Check "service:web" HTTP request failed: Get http://localhost:9999/health: dial tcp 127.0.0.1:9999: connect: connection refused
2018/05/31 06:50:03 [INFO] serf: EventMemberLeave: c1 172.17.0.6
2018/05/31 06:50:03 [DEBUG] raft-net: 172.17.0.5:8300 
accepted connection from: 172.17.0.3:45189
2018/05/31 06:50:08 [INFO] serf: EventMemberJoin: c1 172.17.0.6
2018/05/31 06:50:13 [WARN] agent: Check "service:web" HTTP request failed: Get http://localhost:9999/health: dial tcp 127.0.0.1:9999: connect: connection refused

Эти журналы ошибок легко понять, потому что наша служба определяет API запроса для проверки работоспособности, но мы еще не предоставили эту услугу, поэтому мы продолжаем сообщатьconnection refused

Написать программу мониторинга здоровья

Наш веб-сервис для удобства тестирования просто предоставляет два интерфейса: один для проверки работоспособности и один для тестирования вывода запроса.

Код Go выглядит следующим образом:

package main

import (
  "fmt"
  "net/http"
  "os"
  "log"
)

var hostname, _ = os.Hostname()

func handler(w http.ResponseWriter, r *http.Request) {
    log.Println("receive a request")
    fmt.Fprintf(w, "result from %s\n", hostname)
}

func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("health check")
}

func main() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/health", healthCheckHandler)
    http.ListenAndServe(":9999", nil)
}

После компиляции поместите его в любой каталог s3 и c1

go build -o hc

S3 и c1 соответственно запускают веб-службу в фоновом режиме:

chmod +x hc

nohup /apps/svr/healthcheck/hc  > /apps/svr/healthcheck/log.out &

После запуска веб-сервиса логи s3 и c1 будут показывать:

2018/05/31 07:02:03 [INFO] agent: Synced check "service:web"

Для полного представления услуг, предоставляемых в кластере, доступны определенные API:

$ curl http://localhost:8500/v1/catalog/service/web\?pretty

[
    {
        "ID": "a6d4ea77-47f4-7b7f-480c-dce6f705f091",
        "Node": "c1",
        "Address": "172.17.0.6",
        "Datacenter": "dc1",
        "TaggedAddresses": {
            "lan": "172.17.0.6",
            "wan": "172.17.0.6"
        },
        "NodeMeta": {
            "consul-network-segment": ""
        },
        "ServiceID": "web",
        "ServiceName": "web",
        "ServiceTags": [
            "master"
        ],
        "ServiceAddress": "172.17.0.6",
        "ServiceMeta": {},
        "ServicePort": 10000,
        "ServiceEnableTagOverride": false,
        "CreateIndex": 591,
        "ModifyIndex": 591
    },
    {
        "ID": "7e836265-b197-89fb-e96a-26912ce69954",
        "Node": "s3",
        "Address": "172.17.0.5",
        "Datacenter": "dc1",
        "TaggedAddresses": {
            "lan": "172.17.0.5",
            "wan": "172.17.0.5"
        },
        "NodeMeta": {
            "consul-network-segment": ""
        },
        "ServiceID": "web",
        "ServiceName": "web",
        "ServiceTags": [
            "master"
        ],
        "ServiceAddress": "172.17.0.5",
        "ServiceMeta": {},
        "ServicePort": 10000,
        "ServiceEnableTagOverride": false,
        "CreateIndex": 587,
        "ModifyIndex": 587
    }
]

Из информации, возвращаемой API, мы знаем, что и s3, и c1 являются поставщиками веб-сервисов.В настоящее время мы должны начать думать об одном: теперь, когда у нас есть веб-сервисы, как вызывать их по имени вместо использования Традиционный способ прямого IP-подключения

На самом деле первой реакцией в вашей голове может быть мысль:DNS解析

Обнаружение службы на основе DNS

Посмотрим, кто лидирует в текущем кластере

curl http://localhost:8500/v1/status/leader

"172.17.0.3:8300"

Поскольку текущим лидером является s1, наш тест службы имен DNS основан на s1.

В s1 выполните команду dig

$ dig @127.0.0.1 -p 8600 web.service.consul SRV

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> @127.0.0.1 -p 8600 web.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14484
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul.        IN  SRV

;; ANSWER SECTION:
web.service.consul. 0   IN  SRV 1 1 10000 s3.node.dc1.consul.
web.service.consul. 0   IN  SRV 1 1 10000 c1.node.dc1.consul.

;; ADDITIONAL SECTION:
s3.node.dc1.consul. 0   IN  A   172.17.0.5
s3.node.dc1.consul. 0   IN  TXT "consul-network-segment="
c1.node.dc1.consul. 0   IN  A   172.17.0.6
c1.node.dc1.consul. 0   IN  TXT "consul-network-segment="

;; Query time: 1 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Thu May 31 07:11:29 UTC 2018
;; MSG SIZE  rcvd: 227

Видно, что в РАЗДЕЛЕ ОТВЕТОВ мы получили два результата: есть веб-сервис на s3 и c1. В команде dig мы использовали флаг SRV, потому что в нужной нам служебной информации есть не только ip-адрес, но и номер порта

В это время мы пытаемся остановить веб-сервис на c1:

pkill hc

Перепишите и выполните команду dig

$ dig @127.0.0.1 -p 8600 web.service.consul SRV

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> @127.0.0.1 -p 8600 web.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59668
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul.        IN  SRV

;; ANSWER SECTION:
web.service.consul. 0   IN  SRV 1 1 10000 s3.node.dc1.consul.

;; ADDITIONAL SECTION:
s3.node.dc1.consul. 0   IN  A   172.17.0.5
s3.node.dc1.consul. 0   IN  TXT "consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Thu May 31 07:13:30 UTC 2018
;; MSG SIZE  rcvd: 137

Результат показывает, что на s3 доступен только этот веб-сервис. Когда мы снова восстановим веб-службу c1, служебная информация s1 будет немедленно обновлена:

web.service.consul. 0   IN  SRV 1 1 10000 c1.node.dc1.consul.
web.service.consul. 0   IN  SRV 1 1 10000 s3.node.dc1.consul.

Помните API для веб-сервисов на c1 и s3? Как правило, вы можете позвонитьhttp://ip:9999/Чтобы получить информацию об имени хоста сервера, поскольку веб-сервис уже может быть «обнаружен» на s1, мы пытаемся протестировать его с помощью следующего запроса:

curl http://web.service.consul:9999/

К сожалению, мы сразу получили сообщение об ошибке:

curl: (6) Could not resolve host: web.service.consul; Unknown error

В настоящее время, несмотря на то, что имя службы было зарегистрировано и обнаружено в консуле, программа на сервере все еще не может его распознать, поэтому нам нужны дополнительные средства для решения этой проблемы.

подписаться на dnsmasq

yum -y install dnsmasq

После выполнения убедитесь, что установка прошла успешно:

$ dnsmasq -v

Dnsmasq version 2.76  Copyright (c) 2000-2016 Simon Kelley

Затем измените /etc/dnsmasq.conf.

В основном изменить несколько ключевых конфигураций:

Следующие изменения конфигурации в основном предназначены для облегчения нашего собственного тестирования.Для более стандартизированной конфигурации рекомендуется обратиться к соответствующим документам dnsmasq для самостоятельной настройки.

resolv-file=/etc/resolv.conf

strict-order

server=/consul/172.17.0.3#8600

Затем вам нужно изменить несколько строк конфигурации в /etc/resolv.conf:

nameserver 127.0.0.1
nameserver 172.17.0.3
#nameserver 8.8.8.8

Затем запустите dnsmasq и снова копайте:

dig @127.0.0.1 -p 8600 web.service.consul SRV

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> @127.0.0.1 -p 8600 web.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20604
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul.        IN  SRV

;; ANSWER SECTION:
web.service.consul. 0   IN  SRV 1 1 10000 s3.node.dc1.consul.
web.service.consul. 0   IN  SRV 1 1 10000 c1.node.dc1.consul.

;; ADDITIONAL SECTION:
s3.node.dc1.consul. 0   IN  A   172.17.0.5
s3.node.dc1.consul. 0   IN  TXT "consul-network-segment="
c1.node.dc1.consul. 0   IN  A   172.17.0.6
c1.node.dc1.consul. 0   IN  TXT "consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Thu May 31 08:57:25 UTC 2018
;; MSG SIZE  rcvd: 227

Затем непосредственно копайте web.service.consul, чтобы убедиться, что машина, наконец, распознает службу имен:

$ dig web.service.consul SRV

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> web.service.consul SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61000
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul.        IN  SRV

;; ANSWER SECTION:
web.service.consul. 0   IN  SRV 1 1 10000 s3.node.dc1.consul.
web.service.consul. 0   IN  SRV 1 1 10000 c1.node.dc1.consul.

;; ADDITIONAL SECTION:
s3.node.dc1.consul. 0   IN  A   172.17.0.5
s3.node.dc1.consul. 0   IN  TXT "consul-network-segment="
c1.node.dc1.consul. 0   IN  A   172.17.0.6
c1.node.dc1.consul. 0   IN  TXT "consul-network-segment="

;; Query time: 2 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu May 31 08:58:25 UTC 2018
;; MSG SIZE  rcvd: 227

Хорошо, синтаксический анализ DNS-запросов веб-службы имен в настоящее время выполняется успешно, и, наконец, мы пытаемся запросить веб-API, чтобы узнать, будет ли он правильно возвращать информацию:

$ curl http://web.service.consul:9999
result from 5cade4f672b6

$ curl http://web.service.consul:9999
result from 5cade4f672b6

$ curl http://web.service.consul:9999
result from 579c1deb914f

$ curl http://web.service.consul:9999
result from 5cade4f672b6

$ curl http://web.service.consul:9999
result from 5cade4f672b6

$ curl http://web.service.consul:9999
result from 579c1deb914f

Приведенный выше запрос знает, что s1 успешно разрешает имя web.service.consul, и может успешно вызывать веб-службы s3 и c1.

Пока что расслабляться нельзя, и остался последний шаг для тестирования.Далее закрываем сервис s3 и наблюдаем за вызовом парсинга:

//s3

pkill hc

В это время мы запрашиваем разрешение имени в Интернете:

$ dig web.service.consul SRV

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> web.service.consul SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 650
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul.        IN  SRV

;; ANSWER SECTION:
web.service.consul. 0   IN  SRV 1 1 10000 c1.node.dc1.consul.

;; ADDITIONAL SECTION:
c1.node.dc1.consul. 0   IN  A   172.17.0.6
c1.node.dc1.consul. 0   IN  TXT "consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu May 31 09:03:44 UTC 2018
;; MSG SIZE  rcvd: 137

Мы получаем доступ к curl последовательноweb.service.consul:9999Когда вывод:

result from 5cade4f672b6 //c1

Видно, что s1 в настоящее время может анализировать/обнаруживать только сервисы c1, что означает, что мы достигли динамического «офлайн» сервиса.

Когда мы снова восстанавливаем s3:

$ dig web.service.consul SRV

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> web.service.consul SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9970
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul.        IN  SRV

;; ANSWER SECTION:
web.service.consul. 0   IN  SRV 1 1 10000 c1.node.dc1.consul.
web.service.consul. 0   IN  SRV 1 1 10000 s3.node.dc1.consul.

;; ADDITIONAL SECTION:
c1.node.dc1.consul. 0   IN  A   172.17.0.6
c1.node.dc1.consul. 0   IN  TXT "consul-network-segment="
s3.node.dc1.consul. 0   IN  A   172.17.0.5
s3.node.dc1.consul. 0   IN  TXT "consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu May 31 09:06:47 UTC 2018
;; MSG SIZE  rcvd: 227

Веб-служба s3 может быть автоматически зарегистрирована в кластере служб, и демонстрация этого примера завершена.

Суммировать

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

От построения кластера до предоставления услуги обнаружения, инструмент консул довольно прост в использовании, но все же, высокая доступность услуги является всесторонней.При запуске производственной среды необходимо обратить внимание на конфигурацию времени кэширования DNS, а также поддержку управления доменными именами DNS. Consul — это не волшебная палочка, когда мы проектируем архитектуру, мы должны учитывать разумное взаимодействие между сервисами и более конкретные отказоустойчивые решения. Однако нельзя отрицать, что консул — отличное решение с точки зрения регистрации и обнаружения сервисов.