Files
hse-2026/materials/07-naming-lookup/seminar/consul/readme.md
T
2026-10-21 23:03:28 +03:00

91 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Consul: от имени до ответа приложения
Consul хранит сведения об экземплярах сервисов: их идентификаторы, адреса и результаты проверок работоспособности. Клиент может найти экземпляр по имени сервиса, а затем отправить запрос непосредственно ему.
В стенде у сервиса `orders` два экземпляра: `app-a` и `app-b`. **Предскажите:** если остановить один из них, изменятся ли каталог Consul, список здоровых экземпляров и сохранённый клиентом адрес одновременно?
Все команды выполняются из каталога `seminar`; [подготовка стенда](../readme.md#самостоятельный-запуск-опытов).
## 1. Найти экземпляры
Запустите сервисы и дождитесь, пока оба экземпляра пройдут проверки:
~~~powershell
docker compose up -d --wait consul app-a app-b
docker compose run --rm -T tools python3 consul/client.py wait
~~~
Сравните каталог регистраций и список здоровых экземпляров:
~~~powershell
docker compose run --rm -T tools curl -fsS "http://consul:8500/v1/catalog/service/orders"
docker compose run --rm -T tools curl -fsS "http://consul:8500/v1/health/service/orders?passing=true"
~~~
Каталог содержит зарегистрированные экземпляры независимо от их текущего состояния. Второй запрос с `passing=true` возвращает только экземпляры, прошедшие проверки. В ответе каталога найдите `ServiceName`, `ServiceID`, `ServiceAddress` и `ServicePort`: это имя сервиса, ID экземпляра, его адрес и порт.
Адреса экземпляров можно получить и через DNS-интерфейс Consul:
~~~powershell
docker compose run --rm -T tools dig "@consul" -p 8600 orders.service.consul A +short
docker compose run --rm -T tools dig "@consul" -p 8600 orders.service.consul SRV +short
~~~
Запись **A** содержит IPv4-адрес. Строка **SRV** имеет вид `приоритет вес порт имя-узла`, поэтому позволяет узнать и порт приложения — в нашем случае `8080`. Аргумент `-p 8600` задаёт порт самого DNS-сервера Consul.
**Вопрос:** откуда клиент узнает порт приложения, если запросил только A-запись?
## 2. Сохранить адрес и выполнить запрос
~~~powershell
docker compose run --rm -T tools python3 consul/client.py save
docker compose run --rm -T tools python3 consul/client.py cached
~~~
Команда `save` выбирает первый здоровый экземпляр по ID — `app-a` — и сохраняет его адрес. Команда `cached` обращается по сохранённому адресу. В HTTP-ответе поле `instance` показывает, кто обработал запрос.
Таким образом, клиент сначала получает адрес через HTTP API Consul, затем обращается к приложению. DNS-запросы выше иллюстрируют другой способ поиска адреса.
## 3. Остановить приложение и сравнить результаты
Остановите `app-a` и дождитесь, пока Consul обнаружит сбой:
~~~powershell
docker compose stop app-a
docker compose run --rm -T tools python3 consul/client.py wait --ids app-b
~~~
Теперь сравните каталог, список здоровых экземпляров и DNS-ответ:
~~~powershell
docker compose run --rm -T tools curl -fsS "http://consul:8500/v1/catalog/service/orders"
docker compose run --rm -T tools python3 consul/client.py list
docker compose run --rm -T tools dig "@consul" -p 8600 orders.service.consul A +short
~~~
В каталоге всё ещё есть `app-a`: остановка приложения сама по себе не удаляет регистрацию. Список здоровых экземпляров содержит только `app-b`, а DNS возвращает лишь его адрес.
Сравните запрос по сохранённому адресу с новым поиском:
~~~powershell
docker compose run --rm -T tools python3 consul/client.py cached
docker compose run --rm -T tools python3 consul/client.py fresh
~~~
`cached` завершается с `REQUEST FAILED` и кодом 1 — это ожидаемый результат. `fresh` заново ищет здоровый экземпляр и получает ответ от `app-b`.
Проверки выполняются периодически, поэтому Consul замечает остановку с задержкой. Но даже после обнаружения сбоя сохранённый клиентом адрес не меняется сам. В этом опыте клиент хранит его в файле без срока действия; автоматическое истечение записей рассмотрим в [разделе DNS](../dns/readme.md).
**Вопросы для самопроверки:** гарантирует ли свежий поиск успех следующего запроса? Зачем клиенту тайм-аут и возможность выбрать другой экземпляр? Почему повтор операции с побочным эффектом требует отдельной защиты от повторного выполнения?
## 4. Восстановить исходное состояние
~~~powershell
docker compose start app-a
docker compose run --rm -T tools python3 consul/client.py wait
~~~
В этом стенде один агент Consul и два приложения. Отказоустойчивость самого Consul здесь не проверяется.
Исходники: [приложение и регистрация](app.py), [клиент](client.py). Документация: [регистрация сервиса](https://developer.hashicorp.com/consul/api-docs/agent/service), [DNS-интерфейс](https://developer.hashicorp.com/consul/docs/discover/dns).