Что такое api gateway
Применение API Gateway
В любых сервис-ориентированных подходах к построению архитектуры существует сквозная функциональность и микросервисная архитектура — не исключение. Одним из свойств микросервисов является максимальная изоляция и сквозная функциональность реализуются через слои более высокого уровня, чем уровень бизнес-логики, одним из которых и является API Gateway.
В каком-то смысле API Gateway является аналогом шаблона проектирования «Фасад». Как и фасад, API Gateway предоставляет внешним клиентам общий интерфейс взаимодействия с системой.
Зачем нужен API Gateway?
Представим себе систему
Основной вопрос: как получить данные из конкретного сервиса в микросервисной архитектуре, учитывая высокую гранулярность сервисов и динамику их изменения, постоянно растущее разнообразие устройств со своими требованиями к передаче данных и безопасности?
В этом нам поможет API Gateway. Ниже приведен [не полный] список сквозной функциональности, поддерживаемой шлюзом API:
Аутентификация
Большинство шлюзов поддерживают аутентификацию каждого запроса (или набора запросов). В соотвествии с правилами, заданными для каждого отдельного сервиса, шлюз либо направляет запрос к требуемому сервису, либо возвращает ошибку. Большинство шлюзов дополняют запрос информацией об аутентификации перед отправкой конкретному сервису, это позволяет реализовать специфичную логику для конкретных пользователей в случае необходимости.
Один из подходов к аутентификации показан ниже. В нем клиент отправляет аутентификационные данные в API Gateway, который вызывает AuthService, который может быть реализован, например, с применением OAuth и возвращает клиенту JSON Web Token.
При обращении к какому-либо ресурсу клиент передает JWT как часть запроса. API Gateway перенаправит запрос с JWT нужному сервису. В зависимости от реализации микросервис либо принимает решение о предоставлении доступа самостоятельно, либо запрашивает у сервиса авторизации права на доступ к заданному ресурсу клиента с полученным токеном.
Безопасность
Шлюз нередко выступает в качестве единственной точки входа для внешних запросов. В таком случае на шлюз может быть возложена ответственность за обеспечение безопасности транспортного уровня с использованием различных каналов безопасности или устранением ограничений безопасности, не требуемых во внутреннем сегменте сети. Например, для RESTful HTTP API шлюз может выступить в качестве «SSL Termination Proxy»: между клиентом и шлюзом устанавливается защищенное соединение, в то время как запросы ко внутренним сервисам идут минуя SSL.
Помимо этого шлюз может выполнять следующие функции:
Балансировка нагрузки
В случае возросшей нагрузки, шлюз может обеспечить распределение запросов в соответствии с заданными правилами.
В микросервисах все немного сложнее. Каждый сервис может иметь свои собственные ограничения по масштабируемости. Дизайн API Gateways позволяет учесть эти ограничении. Например, некоторые сервисы могут масштабироваться за счет создания дополнительных инстансов за различными внутренними конечными точками (end points). Шлюз может направить запрос к внутреннему интерфейсу или создать дополнительные сервисы для поддержки возросшей нагрузки.
Диспетчеризация
В шлюзе могут быть реализованы специальные правила диспетчеризации запросов. В больших системах конечные точки (end points) появляются и исчезают постоянно, например, в связи с изменением топологии сети, выводом новой версии сервиса или выводом из эксплуатации старого. Шлюз может работать совместно с процессом Service Registration/Discovery или базами данных, в которых описано, куда направить тот или иной запрос. Это дает командам разработки исключительную гибкость и позволяет в случае падения каких-то сервисов направить запросы на запасный, избежав полного отказа системы.
Разрешение зависимостей
Одна из специфичных для микросервисов проблем — для выполнения полезной работы сервисам может потребоваться множество вызовов других сервисов. Этот феномен назвали «chatty»-архитектурой. Одно из решений — создание виртуальной конечной точки (virtual end point), своеобразного фасада, который распределяет запросы по конкретным сервисам и собирает унифицированный ответ.
Объединение данных из множества сервисов можно сделать и в памяти, что, однако, не всегда эффективно с точки зрения производительности, особенно при объединении больших наборов данных. Здесь стоит обратить внимание на клиента. Если клиент — мобильное приложение с условиях слабой сети, то одно обращение к API Gateway с агрегацией данных внутри может дать серьезное преимущество во времени отклика даже несмотря на то, что по внутренним замерам производительности все стало медленнее.
Преобразования транспортного уровня
Существует три вида преобразований:
При использовании микросервисного архитектурного стиля разработчики вольны самостоятельно выбирать наиболее подходящие для решения проблемы и достижения цели технологии. Это может привести к тому, что данные или протокол, возвращаемые сервисом, могут оказаться несовместимыми с используемыми клиентом технологиями. Шлюз может обеспечить необходимые преобразования.
Например, мобильному приложению и веб-приложению может требоваться различный объем данных, а регулятор умеет работать только по SOAP, тогда как внутри мы используем JSON для передачи данных.
Использование шлюзов API в микрослужбах
В архитектуре микрослужб клиент может взаимодействовать с несколькими внешними службами. Учитывая этот факт, как клиент узнает, какую конечную точку вызывать? Что происходит, когда появляются новые службы или выполняется рефакторинг существующих? Как службы обрабатывают завершение SSL-запросов, аутентификацию и другие операции? Шлюз API поможет ответить на эти вопросы.
Что такое шлюз API?
Шлюз API находится между клиентами и службами. Он выполняет функцию обратного прокси, передавая запросы от клиентов к службам. Он также может выполнять такие специализированные задачи, как аутентификация, завершение SSL-запросов и ограничение частоты. Если этот шлюз не будет развернут, клиенты должны будут отправлять запросы непосредственно к внешним службам. Но при предоставлении клиентам непосредственного доступа к службам могут возникнуть некоторые проблемы.
Шлюз помогает решить эти проблемы, разделив клиенты и службы. Шлюзы могут выполнять разные функции, не все из которых вам могут потребоваться. Функции можно сгруппировать в соответствии со следующими задачами:
Маршрутизация шлюза. Использование шлюза в качестве обратного прокси-сервера для перенаправления запросов на одну или несколько серверных служб с помощью маршрутизации уровня 7. Шлюз предоставляет одну конечную точку для клиентов и позволяет разделить клиенты и службы.
Агрегирование шлюза. Использование шлюза для объединения нескольких отдельных запросов в один. Этот шаблон применяется, если необходимо выполнить одну операцию вызова к нескольким серверным службам. Клиент отправляет один запрос к шлюзу. Этот шлюз распределяет запросы между разными серверными службами, затем объединяет результаты и отправляет их запрашивающему клиенту. Это позволяет сократить число вызовов между клиентом и серверной частью.
Разгрузка шлюза. Использование шлюза для передачи функций отдельных служб в шлюз, в частности специализированных операций. Этот шаблон можно использовать для объединения этих функций, вместо того, чтобы каждая служба отвечала за их реализацию. Это особенно полезно для компонентов, для реализации которых необходимы специальные действия. Например, для аутентификации и авторизации.
Ниже приведены некоторые примеры функций, которые можно передать в шлюз:
Выбор технологии шлюза
Вот несколько параметров для реализации шлюза API в приложении.
Обратный прокси-сервер. Nginx и HAProxy — популярные обратные прокси-серверы, которые поддерживают такие функции, как SSL-запросы, балансировка нагрузки и маршрутизация уровня 7. Оба сервера являются бесплатными продуктами с открытым кодом и платными выпусками, которые предусматривают дополнительные возможности и варианты поддержки. Nginx и HAProxy — это современные продукты с широкими наборами функций и высоким уровнем производительности. Их можно расширить с помощью сторонних модулей или путем написания пользовательских скриптов в Lua. Nginx также поддерживает модуль сценариев на основе JavaScript, называемый nginx JavaScript. Этот модуль был формально назван Нгинскрипт.
Входящий контроллер сетки службы. При использовании слоя взаимодействия между службами, например linkerd или Istio, попробуйте использовать функции, предоставленные входящим контроллером для этой сетки службы. Например, входящий контроллер Istio поддерживает маршрутизацию уровня 7, переадресацию HTTP, повторные попытки и другие функции.
Шлюз приложений Azure. Шлюз приложений — управляемая служба балансировки нагрузки, которая может выполнять маршрутизацию уровня 7 и завершение SSL-запросов. Эта служба также предоставляет брандмауэр веб-приложения (WAF).
Управление API Azure. Служба управления API — это комплексное решение, обеспечивающее публикацию API во внешние и внутренние клиенты. он предоставляет функции, которые удобно использовать для управления общедоступным API, включая ограничение скорости, ограничения IP-адресов и проверку подлинности с помощью Azure Active Directory или других поставщиков удостоверений. Служба управления API не выполняет балансировку нагрузки, поэтому ее следует использовать в сочетании с подсистемой балансировки нагрузки, например шлюзом приложений или обратным прокси-сервером. Сведения об использовании управления API с шлюзом приложений см. в статье интеграция управления API во внутренней виртуальной сети с помощью шлюза приложений.
При выборе технологии шлюза учитывайте следующее:
Features. Все варианты, перечисленные выше, поддерживают маршрутизацию уровня 7, но не обязательно поддерживают остальные функции. Вы можете развернуть несколько шлюзов в зависимости от функций, которые вам нужны.
Развертывание. Шлюз приложений Azure и управление API являются управляемыми службами. Nginx и HAProxy обычно выполняются в контейнерах внутри кластера, а также могут быть развернуты на выделенных виртуальных машинах за пределами кластера. Такая конфигурация изолирует шлюз от остальной части рабочей нагрузки, но увеличивает затраты на управление.
Управление. Когда обновляются службы или добавляются новые, может потребоваться обновить правила маршрутизации шлюза. Рассмотрим, как управлять этим процессом. Аналогичные соображения относятся к управлению SSL-сертификатами, спискам разрешений IP и другим аспектам настройки.
Развертывание Nginx или HAProxy в Kubernetes
Серверы Nginx или HAProxy можно развернуть в Kubernetes как ReplicaSet или DaemonSet, определяющие образ контейнера Nginx или HAProxy. Используйте ConfigMap для хранения файла конфигурации прокси-сервера и подключения ConfigMap в качестве тома. Создайте службу типа LoadBalancer, чтобы предоставлять доступ к шлюзу через Azure Load Balancer.
Или создайте входящий контроллер. Входящий контроллер является ресурсом Kubernetes, который развертывает подсистему балансировки нагрузки или обратный прокси-сервер. Есть несколько вариантов реализации контроллера, в том числе Nginx и HAProxy. Отдельный ресурс, который называется входящим, определяет параметры входящего контроллера, например правила маршрутизации и сертификаты TLS. В этом случае не нужно управлять сложными файлами конфигурации, которые относятся к конкретной технологии прокси-сервера.
Шлюз является потенциально проблемным местом или единой точкой сбоя в системе, поэтому всегда следует развертывать как минимум две реплики для обеспечения высокого уровня доступности. В зависимости от нагрузки в дальнейшем может потребоваться развернуть реплики.
Также попробуйте запустить шлюз на выделенном наборе узлов в кластере. Этот подход отличается следующими преимуществами:
Изоляция. Весь входящий трафик передается на фиксированный набор узлов, которые могут быть изолированы от серверных служб.
Стабильная конфигурация. Если шлюз настроен неправильно, все приложение может стать недоступным.
Производительность. Для шлюза можно использовать определенную конфигурацию виртуальной машины, чтобы увеличить производительность.
Дальнейшие действия
В предыдущих статьях были рассмотрены интерфейсы между микрослужбами или между микрослужбами и клиентскими приложениями. По проекту эти интерфейсы обрабатывают каждую службу как непрозрачную рамку. В частности, микрослужбы никогда не должны предоставлять сведения о реализации того, как они управляют данными. В следующей статье рассматриваются особенности целостности данных и согласованности данных.
Пишем блог на микросервисах – часть 2 «API Gateway»
Теперь пришла очередь API Gateway или API GW.
В нашем c ptimofeev API GW мы реализуем следующие функции:
Для реализации функции конвертация REST/gRPC будем использовать гошную библиотеку grpc-gateway.
Далее в протофайле каждого микросервиса, который хотим опубликовать по REST, необходимо добавить описание option в секции описания интерфейсов сервиса. Здесь собственно указывается путь и метод, по которому будет осуществляться доступ по REST.
На основе этой информации скрипт генерации кода (./bin/protogen.sh) создаст код gRPC сервера (в каталоге микросервиса), gRPC клиента (в каталоге api-gw) и сгенерирует актуальную документацию API (в формате <<имя сервиса>>.swagger.json)
Далее нам нужно написать код HTTP Proxy, который с одной стороны будет HTTP сервером (для обработки REST запросов), а с другой стороны будет gRPC клиентом для наших микросервисов (gRPC серверов).
В начале в секции import подключаем клиентские библиотеки к наших микросервисов
(их нам сгенерил protogen.sh):
Далее указываем адреса и порты на которых «висят» наши gRPC сервисы (значения берем из переменных окружений):
И, наконец, реализуем сам HTTP Proxy:
В настройке подключения к микросервисам мы используем опцию grpc.WithUnaryInterceptor(AccessLogInterceptor), в которую в качестве параметра передаем функцию AccessLogInterceptor. Это не что иное как реализация middleware слоя, т.е. функция AccessLogInterceptor будет выполняться при каждом gRPC вызове дочернего микросервиса.
В свою очередь, в функции AccessLogInterceptor мы уже реализуем механизмы аутентификации, логирования и генерации TraceId.
Если во входящем (REST) запросе в Header был указан атрибут authorization, то парсим и валидируем его в функции CheckGetJWTToken, которая либо возвращает ошибку, либо в случае успеха возвращает UserId и UserRole.
Далее формируем TraceId и заворачиваем его вместе с UserId и UserRole в контекст вызова и осуществляем gRPC вызов нашего микросервиса.
И, наконец, пишем в лог событие вызова сервиса.
Подключаем обработчик ответов.
Пример — обработчик ответа SignIn (обработчик SignUp аналогичен).
Да, демо проекта можно посмотреть здесь, а исходный код здесь.
Наш опыт создания API Gateway
Некоторые компании, в том числе наш заказчик, развивают продукт через партнерскую сеть. Например, крупные интернет-магазины интегрированы со службой доставки — вы заказываете товар и вскоре получаете трекинговый номер посылки. Другой пример — вместе с авиабилетом вы покупаете страховку или билет на аэроэкспресс.
Для этого используется один API, который нужно выдать партнерам через API Gateway. Эту задачу мы и решили. В этой статье расскажем подробности.
Дано: экосистема и API-портал с интерфейсом, где пользователи зарегистрированы, получают информацию и т.п. Нам нужно сделать удобный и надежный API Gateway. В процессе нам нужно было обеспечить
В статье мы расскажем о нашем опыте создания API Gateway, в ходе которого мы решали следующие задачи:
1. Стандартный, который работает следующим образом. Перед подключением пользователь тестирует возможности, затем оплачивает и встраивает на свой сайт. Чаще всего им пользуются в малом и среднем бизнесе.
2. Крупный B2B API Management, когда компания сначала принимает бизнес-решение о подключении, становится партнером компании с контрактным обязательством, после чего подключается к API. И уже после улаживания всех формальностей компания получает тестовый доступ, проходит тестирование и выходит в прод. Но это невозможно без управленческого решения о подключении.
Наше решение
В этой части расскажем о создании API Gateway.
Конечные пользователи создаваемого шлюза к API — партнёры нашего заказчика. Для каждого из них у нас уже хранятся необходимые контракты. Нам нужно будет лишь расширить функциональность, отмечая предоставленный доступ к шлюзу. Соответственно, нужен контролируемый процесс подключения и управления.
Безусловно, можно было взять какое-нибудь готовое решение для решения задачи API Management и создания API Gateway в частности. Например, таким могло быть Azure API Management. Нам оно не подошло, потому что в нашем случае у нас уже был API-портал и огромная экосистема, построенная вокруг него. Все пользователи уже были зарегистрированы, они уже понимали, где и как они могут получить нужную информацию. В API-портале уже существовали нужные интерфейсы, нам лишь был необходим API Gateway. Собственно, его разработкой мы и занялись.
То, что мы называем API Gateway — своего рода прокси. Тут у нас опять был выбор — можно написать свой прокси, а можно выбрать уже что-то готовое. В этом случае мы пошли вторым путём и выбрали связку nginx+Lua. Почему? Нам необходим был надежный, протестированный software, поддерживающий масштабирование. Мы не хотели после реализации проверять и корректность бизнес-логики, и корректность работы прокси.
У любого веб-сервера есть конвейер обработки запроса. В случае nginx он выглядит следующим образом:
Нашей целью было встроиться в этот конвейер в тот момент, где мы можем модифицировать исходный запрос.
Мы хотим создать transparent proxy, чтобы функционально запрос оставался таким, каким и пришёл. Мы лишь контролируем доступ к конечному API, помогаем запросу добраться до него. В случае, если запрос был некорректным, ошибку должен показать конечный API, но не мы. Единственная причина, почему мы можем отклонить запрос — из-за отсутствия доступа у клиента.
Для nginx уже существует расширение на Lua. Lua — скриптовый язык, он очень легковесный и лёгкий в освоении. Таким образом, необходимую логику мы реализовали с помощью Lua.
Конфигурация nginx’a (аналогия route приложения), где и выполняется вся работа, вполне понятная. Примечательна здесь последняя директива — post_action.
Рассмотрим, что происходит в этой конфигурации:
more_clear_input_headers — очищает значение указанных после директивы хэдеров.
lua_need_request_body — регулирует, следует ли прочитать исходное тело запроса перед тем, как выполнять директивы rewrite/access/access_by_lua или нет. По умолчанию nginx не читает тело запроса клиента, и если вам необходимо получить к нему доступ, то данная директива должна иметь значение on.
rewrite_by_lua_file — путь до скрипты, в котором описана логика для модификации запроса
access_by_lua_file — путь до скрипта, в котором описана логика, проверяющая наличие доступа к ресурсу.
proxy_pass — url, на который будет проксироваться запрос.
body_filter_by_lua_file — путь до скрипта, в котором описана логика для фильтрации запроса перед возвращением клиенту.
И, наконец, post_action — официально недокументированная директива, с помощью которой можно выполнять ещё какие-либо действия после того, как ответ отдан клиенту.
Далее расскажем по порядку, как мы решали свои задачи.
Авторизация/аутентификация и модификация запроса
Авторизацию и аутентификацию мы построили с помощью доступов по сертификату. Есть корневой сертификат. Каждому новому клиенту заказчика генерируется его личный сертификат, с которым он может получить доступ к API. Этот сертификат настраивается в секции server настроек nginx.
Может возникнуть справедливый вопрос: что делать с сертифицированным клиентом, если мы внезапно захотели отключить его от системы? Не перевыпускать же сертификаты для всех остальных клиентов.
Так мы плавно и подошли к следующей задаче — модификация исходного запроса. Исходный запрос клиента, вообще говоря, не является валидным для конечной системы. Одна из задач состоит в том, чтобы дописать в запрос недостающие части, чтобы сделать его валидным. Соль в том, что недостающие данные — разные для каждого клиента. Мы знаем, что клиент приходит к нам с сертификатом, с которого мы можем взять отпечаток и вытянуть из базы необходимые данные клиента.
Если в какой-то момент потребуется отключить клиента от нашего сервиса, его данные пропадут из базы и он ничего не сможет делать.
Работа с данными клиента
Нам нужно было обеспечить высокую доступность решения, особенно того, как мы получаем данные клиента. Сложность в том, что первоисточник этих данных — сторонний сервис, который не гарантирует бесперебойную и достаточно высокую скорость работы.
Поэтому нам нужно было обеспечить высокую доступность данных клиентов. В качестве инструмента мы выбрали Hazelcast, который предоставляет нам:
Работа с конечной системой происходит в рамках сессий и есть лимит на максимальное количество. Если же клиент не закрыл сессию, это придётся делать нам.
Если будут заинтересованные, то подробнее расскажем об этой проблеме в отдельной статье. Спойлер — на схемке.
Логирование и мониторинг
Fluentd — open source решение для обеспечения единого слоя логирования приложения. Позволяет собирать логи с разных слоёв приложения, а потом транслировать их в единый источник.
API Gateway работает в K8S, поэтому мы решили добавить контейнер с fluentd в ту же самую подy, чтобы писать логи в имеющийся открытый tcp port fluentd.
Мы также исследовали, как будет вести себя fluentd, если у него не будет связи с Elasticsearch. В течение двух суток в шлюз непрерывно шли запросы, во fluentd отправлялись логи, но у fluentd был забанен IP Elastic. После восстановления связи fluentd отлично перегнал абсолютно все логи в Elastic.
Заключение
Выбранный подход к реализации позволил нам доставить реально работающий продукт в боевую среду всего за 2.5 месяца.
Если когда-нибудь вам доведётся заниматься подобными вещами, советуем в первую очередь четко понять, какую задачу вы решаете и что из ресурсов у вас уже есть. Будьте внимательны к сложностям интеграции с существующими системами управления API.
Поймите для себя, что именно вы собираетесь разрабатывать — только бизнес-логику обработки запросов или, как могло быть в нашем случае, прокси целиком. Не забывайте, что всё, что вы сделаете сами, должно быть впоследствии тщательно протестировано.
Простой API gateway на базе PHP и Lumen
Термин «микросервисы» сегодня у всех на слуху – внезапно это стало очень модно, и многие компании объявляют переход на этот архитектурный паттерн даже толком не разобравшись в нём. Впрочем, обсуждение полезности микросервисов оставим за пределами этой статьи.
Традиционно перед коллекцией микросервисов предлагается дополнительный слой – так называемый API gateway, который решает сразу несколько проблем (они будут перечислены позже). На момент написания этой статьи open source реализаций таких gateway почти нет, поэтому я решил написать свой на PHP с использованием микрофреймворка Lumen (часть Laravel).
В этой статье я покажу насколько это простая задача для современного PHP!
Что такое API gateway?
Если говорить совсем коротко, то API gateway – это умный proxy-сервер между пользователями и любым количеством сервисов (API), отсюда и название.
Необходимость в этом слое появляется сразу же при переходе на паттерн микросервисов:
Nginx выпустили неплохую бесплатную электронную книгу посвященную микросервисам и API gateway – советую почитать всем, кому интересен этот паттерн.
Существующие варианты
Почему PHP и Lumen?
С выходом версии 7 PHP стал высокопроизводительным, а с появлением фреймфорков вроде Laravel и Symfony – PHP доказал миру, что может быть красивым и функциональным. Lumen, являясь «очищенной» быстрой версией Laravel здесь идеально подходит, ведь нам не нужны будут сессии, шаблоны и прочие возможности full stack приложений.
Кроме того, у меня просто больше опыта с PHP и Lumen, а разворачивая полученное приложение через Docker – будущим пользователям вообще будет не важен язык, на котором оно написано. Это просто слой, который выполняет свою роль!
Выбранная терминология
Мною предлагается следующая архитектура и соответствующая ей терминология. В коде буду придерживаться этих терминов, чтобы не запутаться:
Само приложение решил назвать Vrata, потому что «врата» на русском это почти «gateway», а ещё миру не хватает приложений с русскими названиями )
Непосредственно за «вратами» находится количество N микросервисов – API сервисов, способных отвечать на web-запросы. У каждого сервиса может быть любое количество экземпляров, поэтому API gateway будет выбирать конкретный экземпляр через так называемый реестр сервисов.
Каждый сервис предлагает какое-то количество ресурсов (на языке REST), а у каждого ресурса может быть несколько возможных действий. Достаточно простая и логичная структура для любого опытного в REST программиста.
Требования к Vrata
Ещё не приступив к коду, можно сразу определить некоторые требования к будущему приложению:
Реализация
Аутентификация
В этом направлении почти не пришлось работать – достаточно было поправить Laravel Passport под Lumen и мы получили поддержку всех современных OAuth2 фич, включая JWT. Мой маленький пакет-порт опубликован на GitHub/Packagist и кто-то его уже устанавливает.
Маршруты и контроллер
Все низлежащие маршруты с микросервисов импортируются в Vrata из конфигурационного файла в формате JSON. В момент запуска в service provider происходит добавление этих маршрутов:
А тем временем в базе маршрутов:
Теперь каждому публичному (и разрешенному в конфигах) маршруту с микросервисов соответствует маршрут на API gateway. Кроме того, добавлены также синтетические или объединенные запросы, которые существуют только на этом шлюзе. Все запросы уходят в один и тот же контроллер:
Вот так контроллер обрабатывает любой GET-запрос:
В качестве HTTP-клиента выбран Guzzle, который прекрасно справляется с async-запросами, а также имеет готовые средства для integration-тестирования.
Составные запросы
Уже работают сложные, составные запросы – это когда одному маршруту на шлюзе соответствует любое количество маршрутов на разных микросервисах. Вот рабочий пример:
Как видим, сложные маршруты уже доступны и обладают неплохим набором фич – можно выделать критически важные из них, можно делать параллельные запросы, можно использовать ответ одного сервиса в запросе к другому и так далее. Помимо всего прочего, на выходе прекрасная производительность – всего 56 миллисекунд на получение суммарного ответа (загрузка Lumen и три фоновых запроса, все микросервисы с базами данных).
Реестр сервисов
Это пока самая слабая часть – реализован только один очень простой метод: DNS. Несмотря на всю его примитивность, он отлично работает в среде вроде Docker Cloud или AWS, где сам провайдер наблюдает за группой сервисов и динамически редактирует DNS-запись.
В настоящий момент Vrata просто берет hostname сервиса, не вникая – облако это или один физический компьютер. Самым популярным реестром на сегодня, пожалуй, является Consul, и именно его стоит добавить следующим.
Суть работы реестра очень проста – надо хранить таблицу живых и мертвых экземпляров сервиса, выдавая адреса конкретных экземпляров когда надо. AWS и Docker Cloud (и многие другие) умеют это делать за вас, предоставляя вам один «волшебный» hostname, который всегда работает.
Образ Docker
Говоря о микросервисах просто нельзя не упомянуть Docker – одну из самых «горячих» технологий последних пары лет. Микросервисы, как правило, тестируются и деплоятся именно как образы Docker – это стало стандартной практикой, поэтому мы быстро подготовили публичный образ в Docker Hub.
Одна команда, введённая в терминале любой OS X, Windows или Linux машины, и у вас работает мой шлюз Vrata:
Всю конфигурацию можно передать в переменных окружения в формате JSON.
Послесловие
Приложение (шлюз) уже используется на практике в компании, где я работаю. Весь код в репозитории на GitHub. Если кто-либо хочет поучаствовать в разработке – милости просим 🙂
Так как составные запросы как по идее, так и по реализации очень напоминают продвигаемый Facebook формат запросов GraphQL (в противовес REST), то одна из приоритетных будущих фич – поддержка GraphQL-запросов.