При разработке приложений необходимо уделять особое внимание архитектуре. Если изначально этого не сделать, проблемы масштабирования могут появиться внезапно (а иногда могут не иметь решения). Масштабирование приложения и эффективное использование ресурсов на начальном этапе — это сэкономленные месяцы работы в дальнейшем.
Для предотвращения подобных проблем часто используют распределенную архитектуру, то есть архитектуру с возможностью горизонтального масштабирования всех компонентов. Но к сожалению, при реализации SOA возникают новые проблемы, а именно: связность и сложность конфигурации сервисов.
В данной статье мы расскажем об одном из discovery-сервисов под названием Consul, с помощью которого можно решить вышеизложенные проблемы и сделать архитектуру более прозрачной и понятной.
Проектируя приложение как набор слабо связанных компонентов, мы изначально получаем возможность масштабирования любого компонента.
SOA (Service Oriented Architecture) — это архитектурный паттерн, описывающий архитектуру приложения в виде автономных компонентов со слабой связанностью, общающихся между собой по стандартным протоколам (например REST). Логическим продолжением (или подмножеством) SOA является микросервисная архитектура. Она базируется на увеличении количества сервисов вместо увеличения функциональности конкретного сервиса (отражение принципа Single Responsibility в архитектуре) и глубокой интеграции с continuous-процессами.
Если заниматься реализацией микросервисной архитектуры, то, несомненно, ответственность за взаимодействие наших сервисов переходит в сторону инфраструктурного решения нашего приложения. Сервисы, которые соответствуют принципу Single Responsibility, умеют только принимать запрос и возвращать ответ. При этом нужно балансировать трафик между узлами системы, нужно связать, пусть и слабо, но все равно зависимые друг от друга сервисы между собой. И конечно же нам нужно реагировать на изменения конфигурации нашей системы:
В любой системе это непрерывный и сложный процесс, но при помощи сервиса discovery мы сможем его контролировать и сделать его прозрачнее.
Discovery — это инструмент (или набор инструментов) для обеспечения связи между компонентами архитектуры. Используя discovery мы обеспечиваем связность между компонентами приложения, но не связанность. Discovery можно рассматривать как некий реестр метаинформации о распределенной архитектуре, в котором хранятся все данные о компонентах. Это позволяет реализовать взаимодействие компонентов с минимальным ручным вмешательством (т.е. в соответствии с принципом ZeroConf).
Discovery-сервис обеспечивает три основных функции, на которых базируется связность в рамках распределенной архитектуры:
Раскроем значения каждого пункта подробно:
Консистентность
Распределенная архитектура подразумевает, что компоненты можно масштабировать горизонтально, при этом они должны владеть актуальной информацией о состоянии кластера. Discovery-сервис обеспечивает (де)централизованное хранилище и доступ к нему для любого узла. Компоненты могут сохранять свои данные и информация будет доставлена ко всем заинтересованным участникам кластера.
Регистрация и мониторинг
Вновь добавляемые сервисы должны сообщить о себе, а уже запущенные обязаны проходить постоянную проверку на доступность. Это является необходимым условием для автоматической конфигурации кластера. Балансеры трафика и зависимые ноды обязательно должны иметь информацию о текущей конфигурации кластера для эффективного использования ресурсов.
Обнаружение
Под обнаружением подразумевается механизм поиска сервисов, например, по ролям которые они выполняют. Мы можем запросить местоположение для всех сервисов определенной роли, не зная их точного количества и конкретных адресов, а зная лишь адрес discovery-сервиса.
В данной статье рассматривается реализация discovery на базе Consul.
Consul — это децентрализованный отказоустойчивый discovery-сервис от компании HashiCorp (которая разрабатывает такие продукты как Vagrant, TerraForm, Otto, Atlas и другие).
Consul является децентрализованным сервисом, то есть Consul agent устанавливается на каждый хост и является полноправным участником кластера. Таким образом, сервисам не нужно знать адрес discovery в нашей сети, все запросы к discovery выполняются на локальный адрес 127.0.0.1.
Для распространения информации использует алгоритмы, которые базируются на модели eventual consistency.
Агенты для распространения информации используют протокол gossip.
Серверы для выбора лидера используют алгоритм Raft.
Лидер — это сервер, который принимает все запросы на изменение информации. Если провести аналогию с БД, то это master в контексте master/slave — репликации. Все остальные серверы реплицируют данные с лидера. Ключевое отличие от БД-репликации в том, что в случае выхода из строя лидера все остальные серверы запускают механизм выборов нового лидера и после выборов автоматически начинают реплицироваться с него. Механизм переключения полностью автоматический и не требует вмешательства администратора.
Каждый инстанс может работать в двух режимах: агент и сервер. Разница в том, что агент является точкой распространения информации, а сервер — точкой регистрации. Т.е. агенты принимают запросы только на чтение, а сервер может выполнять изменения уже имеющейся информации (регистрация и удаление сервисов). Фактически мы, в любом случае, выполняем запрос к локальному адресу, разница лишь в том, что запрос на чтение будет обработан агентом на локальном хосте, а запрос на изменение данных будет переадресован лидеру, который сохранит и распространит данные по всему кластеру. Если наш локальный агент не является лидером в данный момент, то наш запрос на изменение будет полностью обработан локально и распространен по кластеру.
Consul кластер представляет собой сеть связанных узлов, на которых запущены сервисы, зарегистрированные в discovery. Consul гарантирует, что информация о кластере будет распространена по всем участникам кластера и доступна по запросу. Также реализована поддержка не только однорангового, но и многорангового, разделенного по зонам, кластера, которые в терминологии Consul называются датацентрами. При помощи Consul можно работать как с конкретным датацентром, так и выполнять действия над любым другим. Датацентры не изолированы друг от друга в рамках discovery. Агент в одном ДЦ может получить информацию из другого ДЦ, что может помочь в построении эффективного решения для распределенной системы.
Агенты Consul, запущенные в режиме server, помимо своей основной роли, получают еще и роль потенциального лидера кластера. Рекомендуется использовать в кластере не менее трех агентов в режиме server для обеспечения отказоустойчивости. Использования режима server не накладывает никаких ограничений на основную функциональность агента.
При вводе нового узла в кластер, нам необходимо знать адрес любого узла в кластере. Выполнив команду:
мы регистрируем новый узел в кластере и, спустя короткое время, информация о состоянии всего кластера будет доступна этому узлу. Соответственно, новый узел окажется доступным для запросов от остальных узлов.
В Consul мы можем зарегистрировать наш сервис двумя способами:
Рассмотрим оба случая чуть подробнее.
При помощи HTTP API, предоставляемого Consul, есть возможность сделать корректную регистрацию компонента и удаление сервиса в discovery. Помимо этих двух состояний, можно использовать состояние
Рассмотрим пример запроса регистрации компонента (JSON должен быть передан в PUT-запросе):
Пример запроса на удаление компонента из каталога:
Пример запроса на перевод сервиса в режим maintenance:
При помощи флага enable мы можем переключать состояние и добавить необязательный параметр reason, который содержит текстовое описание причины перевода компонента в режим обслуживания.
Если нам необходимо зарегистрировать какой-либо внешний сервис и у нас нет возможности “научить” его регистрироваться в Consul самостоятельно, то мы можем зарегистрировать его не как сервис-провайдер, а именно как внешний сервис (external service). После регистрации мы сможем получить данные о внешнем сервисе через DNS:
Помимо HTTP API вы можете использовать конфигурационные файлы агента с описанием сервисов.
Во второй части мы завершим рассказ о сервисе Consul, а именно расскажем о его следующих функциях:
И конечно же подведем итоги работы с Consul.
Для предотвращения подобных проблем часто используют распределенную архитектуру, то есть архитектуру с возможностью горизонтального масштабирования всех компонентов. Но к сожалению, при реализации SOA возникают новые проблемы, а именно: связность и сложность конфигурации сервисов.
В данной статье мы расскажем об одном из discovery-сервисов под названием Consul, с помощью которого можно решить вышеизложенные проблемы и сделать архитектуру более прозрачной и понятной.
Распределенные архитектуры(SOA) и проблемы их построения
Проектируя приложение как набор слабо связанных компонентов, мы изначально получаем возможность масштабирования любого компонента.
SOA (Service Oriented Architecture) — это архитектурный паттерн, описывающий архитектуру приложения в виде автономных компонентов со слабой связанностью, общающихся между собой по стандартным протоколам (например REST). Логическим продолжением (или подмножеством) SOA является микросервисная архитектура. Она базируется на увеличении количества сервисов вместо увеличения функциональности конкретного сервиса (отражение принципа Single Responsibility в архитектуре) и глубокой интеграции с continuous-процессами.
Если заниматься реализацией микросервисной архитектуры, то, несомненно, ответственность за взаимодействие наших сервисов переходит в сторону инфраструктурного решения нашего приложения. Сервисы, которые соответствуют принципу Single Responsibility, умеют только принимать запрос и возвращать ответ. При этом нужно балансировать трафик между узлами системы, нужно связать, пусть и слабо, но все равно зависимые друг от друга сервисы между собой. И конечно же нам нужно реагировать на изменения конфигурации нашей системы:
- Cервисы постоянно добавляются.
- Hекоторые сервисы перестают реагировать на healthcheck.
- Новые компоненты появляются в системе и нужно максимально эффективно распространить информацию о них.
- Обновляются версии отдельных компонентов — ломается обратная совместимость.
В любой системе это непрерывный и сложный процесс, но при помощи сервиса discovery мы сможем его контролировать и сделать его прозрачнее.
Что такое discovery?
Discovery — это инструмент (или набор инструментов) для обеспечения связи между компонентами архитектуры. Используя discovery мы обеспечиваем связность между компонентами приложения, но не связанность. Discovery можно рассматривать как некий реестр метаинформации о распределенной архитектуре, в котором хранятся все данные о компонентах. Это позволяет реализовать взаимодействие компонентов с минимальным ручным вмешательством (т.е. в соответствии с принципом ZeroConf).
Роль discovery в процессе построения распределенной архитектуры
Discovery-сервис обеспечивает три основных функции, на которых базируется связность в рамках распределенной архитектуры:
- Консистентность метаинформации о сервисах в рамках кластера.
- Механизм для регистрации и мониторинга доступности компонентов.
- Механизм для обнаружения компонентов.
Раскроем значения каждого пункта подробно:
Консистентность
Распределенная архитектура подразумевает, что компоненты можно масштабировать горизонтально, при этом они должны владеть актуальной информацией о состоянии кластера. Discovery-сервис обеспечивает (де)централизованное хранилище и доступ к нему для любого узла. Компоненты могут сохранять свои данные и информация будет доставлена ко всем заинтересованным участникам кластера.
Регистрация и мониторинг
Вновь добавляемые сервисы должны сообщить о себе, а уже запущенные обязаны проходить постоянную проверку на доступность. Это является необходимым условием для автоматической конфигурации кластера. Балансеры трафика и зависимые ноды обязательно должны иметь информацию о текущей конфигурации кластера для эффективного использования ресурсов.
Обнаружение
Под обнаружением подразумевается механизм поиска сервисов, например, по ролям которые они выполняют. Мы можем запросить местоположение для всех сервисов определенной роли, не зная их точного количества и конкретных адресов, а зная лишь адрес discovery-сервиса.
Consul.io как реализация discovery
В данной статье рассматривается реализация discovery на базе Consul.
Consul — это децентрализованный отказоустойчивый discovery-сервис от компании HashiCorp (которая разрабатывает такие продукты как Vagrant, TerraForm, Otto, Atlas и другие).
Consul является децентрализованным сервисом, то есть Consul agent устанавливается на каждый хост и является полноправным участником кластера. Таким образом, сервисам не нужно знать адрес discovery в нашей сети, все запросы к discovery выполняются на локальный адрес 127.0.0.1.
Что еще необходимо знать про Consul:
Для распространения информации использует алгоритмы, которые базируются на модели eventual consistency.
Агенты для распространения информации используют протокол gossip.
Серверы для выбора лидера используют алгоритм Raft.
Лидер — это сервер, который принимает все запросы на изменение информации. Если провести аналогию с БД, то это master в контексте master/slave — репликации. Все остальные серверы реплицируют данные с лидера. Ключевое отличие от БД-репликации в том, что в случае выхода из строя лидера все остальные серверы запускают механизм выборов нового лидера и после выборов автоматически начинают реплицироваться с него. Механизм переключения полностью автоматический и не требует вмешательства администратора.
Каждый инстанс может работать в двух режимах: агент и сервер. Разница в том, что агент является точкой распространения информации, а сервер — точкой регистрации. Т.е. агенты принимают запросы только на чтение, а сервер может выполнять изменения уже имеющейся информации (регистрация и удаление сервисов). Фактически мы, в любом случае, выполняем запрос к локальному адресу, разница лишь в том, что запрос на чтение будет обработан агентом на локальном хосте, а запрос на изменение данных будет переадресован лидеру, который сохранит и распространит данные по всему кластеру. Если наш локальный агент не является лидером в данный момент, то наш запрос на изменение будет полностью обработан локально и распространен по кластеру.
Использование Consul в кластере
Consul кластер представляет собой сеть связанных узлов, на которых запущены сервисы, зарегистрированные в discovery. Consul гарантирует, что информация о кластере будет распространена по всем участникам кластера и доступна по запросу. Также реализована поддержка не только однорангового, но и многорангового, разделенного по зонам, кластера, которые в терминологии Consul называются датацентрами. При помощи Consul можно работать как с конкретным датацентром, так и выполнять действия над любым другим. Датацентры не изолированы друг от друга в рамках discovery. Агент в одном ДЦ может получить информацию из другого ДЦ, что может помочь в построении эффективного решения для распределенной системы.
Агенты Consul, запущенные в режиме server, помимо своей основной роли, получают еще и роль потенциального лидера кластера. Рекомендуется использовать в кластере не менее трех агентов в режиме server для обеспечения отказоустойчивости. Использования режима server не накладывает никаких ограничений на основную функциональность агента.
При вводе нового узла в кластер, нам необходимо знать адрес любого узла в кластере. Выполнив команду:
consul join node_ip_address
мы регистрируем новый узел в кластере и, спустя короткое время, информация о состоянии всего кластера будет доступна этому узлу. Соответственно, новый узел окажется доступным для запросов от остальных узлов.
Типы узлов: internal, external
В Consul мы можем зарегистрировать наш сервис двумя способами:
- Использовать HTTP API или конфигурационный файл агента, но только в том случае если ваш сервис может общаться с Consul самостоятельно.
- Зарегистрировать сервис как 3d-party компонент, в случае если сервис не может общаться с Consul.
Рассмотрим оба случая чуть подробнее.
При помощи HTTP API, предоставляемого Consul, есть возможность сделать корректную регистрацию компонента и удаление сервиса в discovery. Помимо этих двух состояний, можно использовать состояние
maintenance
. В этом режиме сервис помечается как недоступный и перестает отображаться в DNS и API-запросах.Рассмотрим пример запроса регистрации компонента (JSON должен быть передан в PUT-запросе):
http://localhost:8500/v1/agent/service/register
{
"ID": "redis1",
"Name": "redis",
"Tags": [
"master",
"v1"
],
"Address": "127.0.0.1",
"Port": 8000,
"Check": {
"Script": "/usr/local/bin/check_redis.py",
"HTTP": "http://localhost:5000/health",
"Interval": "10s",
"TTL": "15s"
}
}
Пример запроса на удаление компонента из каталога:
http://localhost:8500/v1/agent/service/deregister/[ServiceID]
Пример запроса на перевод сервиса в режим maintenance:
http://localhost:8500/v1/agent/service/maintenanse/[ServiceID]?enable=true|false
При помощи флага enable мы можем переключать состояние и добавить необязательный параметр reason, который содержит текстовое описание причины перевода компонента в режим обслуживания.
Если нам необходимо зарегистрировать какой-либо внешний сервис и у нас нет возможности “научить” его регистрироваться в Consul самостоятельно, то мы можем зарегистрировать его не как сервис-провайдер, а именно как внешний сервис (external service). После регистрации мы сможем получить данные о внешнем сервисе через DNS:
$ curl -X PUT -d '{"Datacenter": "dc1", "Node": "google",
"Address": "www.google.com",
"Service": {"Service": "search", "Port": 80}}'
http://127.0.0.1:8500/v1/catalog/register
Помимо HTTP API вы можете использовать конфигурационные файлы агента с описанием сервисов.
Во второй части мы завершим рассказ о сервисе Consul, а именно расскажем о его следующих функциях:
- Интерфейс DNS.
- HTTP API.
- Health Checks.
- K/V storage.
И конечно же подведем итоги работы с Consul.