Статьи

Микросервисы для разработчиков Java: шлюзы и агрегаторы API

1. Введение

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

Типичному веб-интерфейсу или мобильному приложению может потребоваться обмен данными с десятками микросервисов , что, например, в случае бэкэндов службы REST (ful) требует знания того, как найти каждую конечную точку, о которой идет речь. Использование обнаружения служб или реестра служб в таких обстоятельствах нецелесообразно, поскольку эти компоненты инфраструктуры не должны быть общедоступными. Это не оставляет много опций, кроме предварительного заполнения сведений о подключении службы в некоторых настройках конфигурации (обычно файлах конфигурации), которые клиент может использовать.

В целом, этот подход работает, но поднимает другую проблему: количество циклов между клиентами и сервисами стремительно растет. Это особенно болезненно для мобильных клиентов, которые часто общаются по довольно медленным и ненадежным сетевым каналам. Мало того, это может быть довольно дорого в случае облачных развертываний, когда многие облачные провайдеры взимают плату за количество запросов (или вызовов). Проблема реальна и требует решения, но как? В этот момент на сцене появляется шаблон шлюза API .

Существует много формальных и неформальных определений того, что на самом деле представляет собой API-шлюз , а приведенное ниже пытается охватить все его аспекты несколькими предложениями.

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

https://en.wikipedia.org/wiki/API_management

Более абстрактное и более короткое описание определения шлюза API взято из отличного поста в блоге . API Gateway — это не новый Unicorn , очень рекомендуемое чтение.

Шлюз API — это способ решения проблемы использования клиентами своих сценариев использования в микросервисной экосистеме в рамках шаблона микросервиса — https://www.krakend.io/blog/what-is-an-api-gateway /

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

2. Зуул 2

Zuul родился в Netflix и служит входной дверью для всех запросов, поступающих в их потоковые бэкэнды. Это сервис шлюза (также иногда называемый пограничным сервисом), который обеспечивает динамическую маршрутизацию, мониторинг, отказоустойчивость, безопасность и многое другое. Недавно он прошел серьезную модернизацию и был переименован в Zuul 2 следующего поколения.

По сути, Zuul предоставляет базовые строительные блоки, но все остальное, например, правила маршрутизации, подлежит настройке с помощью фильтров и абстракций конечных точек. Такие расширения должны быть реализованы в Groovy , выбранном языке сценариев. Например, платформа JCG Car Rentals активно использует Zuul для передачи запросов всем своим службам, предоставляя собственную реализацию входящего фильтра.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Routes extends HttpInboundSyncFilter {
    @Override
    int filterOrder() {
        return 0
    }
 
    @Override
    boolean shouldFilter(HttpRequestMessage httpRequestMessage) {
        return true
    }
 
    @Override
    HttpRequestMessage apply(HttpRequestMessage request) {
        SessionContext context = request.getContext()
         
        if (request.getPath().equals("/inventory") || request.getPath().startsWith("/inventory/")) {
            request.setPath("/api" + request.getPath())
            context.setEndpoint(ZuulEndPointRunner.PROXY_ENDPOINT_FILTER_NAME)
            context.setRouteVIP("inventory")
        } else if (request.getPath().equals("/customers") || request.getPath().startsWith("/customers/")) {
            request.setPath("/api" + request.getPath())
            context.setEndpoint(ZuulEndPointRunner.PROXY_ENDPOINT_FILTER_NAME)
            context.setRouteVIP("customers")
        } else if (request.getPath().equals("/reservations") || request.getPath().startsWith("/reservations/")) {
            request.setPath("/api" + request.getPath())
            context.setEndpoint(ZuulEndPointRunner.PROXY_ENDPOINT_FILTER_NAME)
            context.setRouteVIP("reservations")
        } else if (request.getPath().equals("/payments") || request.getPath().startsWith("/payments/")) {
            request.setPath("/api" + request.getPath())
            context.setEndpoint(ZuulEndPointRunner.PROXY_ENDPOINT_FILTER_NAME)
            context.setRouteVIP("payments")
        } else {
            context.setEndpoint(NotFoundEndpoint.class.getCanonicalName())
        }
 
        return request
    }
}

Zuul очень гибок и дает вам полный контроль над стратегиями управления API. Помимо многих других функций, он очень хорошо интегрируется с Eureka для обнаружения сервисов и Ribbon для балансировки нагрузки . Инициализация сервера довольно проста.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public class Bootstrap {
    public static void main(String[] args) {
        Server server = null;
 
        try {
            ConfigurationManager.loadCascadedPropertiesFromResources("application");
            final Injector injector = InjectorBuilder.fromModule(new RentalsModule()).createInjector();
            final BaseServerStartup serverStartup = injector.getInstance(BaseServerStartup.class);
            server = serverStartup.server();
            server.start(true);
        } catch (final IOException ex) {
            throw new UncheckedIOException(ex);
        } finally {
            // server shutdown
            if (server != null) {
                server.stop();
            }
        }
    }
}

Это проверено годами в бою, и его эффективность в качестве шлюза API и / или пограничного сервиса доказана в масштабе Netflix .

3. Весенние Облачные Врата

Spring Cloud Gateway , член платформы Spring , — это библиотека, облегчающая построение вашего собственного API-шлюза с использованием Spring MVC и Spring WebFlux . Первое поколение Spring Cloud Gateway было построено поверх Zuul, но это уже не так. Новое поколение сменило силовую передачу на собственный проектный реактор Spring и его экосистему.

Давайте посмотрим, как платформа JCG Car Rentals могла бы использовать Spring Cloud Gateway, чтобы иметь крайнюю точку входа для своих API.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
server:
  port: 17001
 
spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
      - id: inventory
        uri: lb://inventory-service
        predicates:
        - Path=/inventory/**
        filters:
        - RewritePath=/(?.*), /api/$\{path}
      - id: customers
        uri: lb://customer-service
        predicates:
        - Path=/customers/**
        filters:
        - RewritePath=/(?.*), /api/$\{path}
      - id: reservations
        uri: lb://reservation-service
        predicates:
        - Path=/reservations/**
        filters:
        - RewritePath=/(?.*), /api/$\{path}
      - id: payments
        uri: lb://payment-service
        predicates:
        - Path=/payments/**
        filters:
        - RewritePath=/(?.*), /api/$\{path}
         
eureka:
  instance:
    appname: api-gateway
    preferIpAddress: true
  client:
    register-with-eureka: false
    fetch-registry: true
    healthcheck:
      enabled: true
    service-url:
      defaultZone: http://localhost:20200/eureka/

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

1
2
3
4
5
6
7
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayStarter {
    public static void main(String[] args) {
        SpringApplication.run(GatewayStarter.class, args);
    }
}

Как и в Zuul 2 , Spring Cloud Gateway позволяет вам нарезать и вырезать любые функции, которые требуются вашей архитектуре микросервисов от шлюза API . Однако это также становится вашей обязанностью поддерживать и изучать, как управлять им.

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

4. HAProxy

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

5. Микрогейтвей

Microgateway от StrongLoop — отличная иллюстрация инноваций, происходящих в мире JavaScript и особенно в экосистеме Node.js.

Microgateway — это ориентированная на разработчиков расширяемая платформа шлюза, написанная на Node.js для обеспечения доступа к микросервисам и API. https://strongloop.com/projects/

6. Конг

Kong является одним из первых шлюзов API, появившихся в Mashape для решения проблем их развертывания микросервисов .

Kong — это масштабируемый API-уровень с открытым исходным кодом (также известный как API-шлюз или API Middleware). Kong работает перед любым RESTful API и расширяется с помощью плагинов , которые предоставляют дополнительные функциональные возможности и услуги помимо базовой платформы. https://konghq.com/about-kong/

Написанный на Lua , Kong построен на прочном фундаменте nginx (о котором мы говорили в предыдущей части руководства) и распространяется вместе с OpenResty , полноценной веб-платформой на основе nginx .

7. Gravitee.io

От сфокусированных решений API-шлюзов мы постепенно переходим к более навороченным вариантам, начиная с Gravitee.io , платформы API с открытым исходным кодом.

Gravitee.io — это гибкая, легкая и быстро работающая платформа API с открытым исходным кодом, которая помогает вашей организации точно контролировать, кто, когда и как пользователи получают доступ к вашим API. https://gravitee.io/

Платформа Gravitee.io состоит из трех основных компонентов: в центре находится API Gateway , окруженный Management API и Management Web Portal .

8. Тык

Tyk — это еще один пример легкой и всеобъемлющей платформы API, в основе которой лежит шлюз API .

Tyk — это быстрый, масштабируемый и современный API-шлюз с открытым исходным кодом. Из коробки Tyk предлагает платформу управления API со шлюзом API, аналитикой API, порталом разработчика и панелью управления API. https://tyk.io/

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

9. Посол

Гиперпопулярность Kubernetes привела к появлению API-шлюзов, которые могли бы работать на нём. Одним из пионеров в этой категории является посол Datawire .

Ambassador — это открытый API-интерфейс Kubernetes с открытым исходным кодом, построенный на Envoy и предназначенный для микросервисов. Посол по сути служит входным контроллером Посланника , но с гораздо большим количеством функций. https://github.com/datawire/ambassador

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

10. Gloo

Еще один известный представитель Kubernetes-собственного шлюза API — это Gloo , с открытым исходным кодом и поддерживаемый solo.io.

Gloo — это многофункциональный входной контроллер Kubernetes и API-шлюз следующего поколения. Gloo является исключительным в своей маршрутизации на уровне функций; поддержка устаревших приложений, микросервисов и серверов; его возможности обнаружения; его многочисленные особенности; и его тесная интеграция с ведущими проектами с открытым исходным кодом. https://gloo.solo.io/

Gloo построен на вершине посланника . Плавная интеграция с рядом серверных предложений делает Gloo по-настоящему уникальным решением.

11. Бэкэнды для Frontends (BFF)

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

Шлюз API потенциально может помочь, часто торгуя удобством для взрыва API, адаптированных для каждого потребителя. Для устранения этих недостатков была разработана модель Backends For Frontends (или BFF ), получившая некоторую популярность. В частности, при поддержке GraphQL это становится очень эффективным решением проблемы.

Давайте быстро рассмотрим платформу JCG Car Rentals, включающую компонент BFF , основанный на стеке GraphQL и Apollo GraphQL . Сама реализация использует REST Data Source, чтобы прозрачно делегировать работу службе резервирования, службе поддержки клиентов и / или службе инвентаризации потребителю, который просто запрашивает то, что ему нужно, с помощью запросов GraphQL .

01
02
03
04
05
06
07
08
09
10
query {
  reservations(customerId: $customerId) {
    from
    to
  }
  profile(id: $customerId) {
    firstName
    lastName
  }
}

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

12. Создайте свой собственный

Если ни один из существующих подходов не выглядит подходящим для ваших потребностей в архитектуре микросервиса , всегда есть возможность создать свой собственный. Использование полноценных интеграционных сред, таких как Apache Camel или Spring Integration, может быть лучшим и кратчайшим путем для вас. Более того, если вы уже делаете ставки на эти фреймворки, использование знакомой парадигмы гораздо эффективнее, чем изучение еще одной технологии (предупреждение спойлера, не позволяйте обману вводить вас в заблуждение).

13. Облако

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

Один интересный вопрос, который нужно затронуть, это понять, какова роль шлюзов API в безсерверных вычислениях ? Не будет преувеличением сказать, что шлюз API является очень ключевым компонентом в такой архитектуре, поскольку он обеспечивает одну из точек входа в модель выполнения без сервера . Если обычное развертывание микросервисов может обойтись без API-шлюза , без сервера не обойтись без него.

14. На темной стороне

Борьба за лидерство в нише шлюза API вынуждает поставщиков внедрять все больше и больше функций в свои продукты, что существенно меняет определение того, что такое API-шлюз , и ведет прямо к кризису идентификации . Эта проблема исключительно хорошо описана ThoughtWorks в их потрясающей технологической радаре .

Мы по-прежнему обеспокоены бизнес-логикой и согласованием процессов, реализованных в промежуточном программном обеспечении, особенно там, где это требует экспертных навыков и инструментов при создании единых точек масштабирования и контроля. Продавцы на высококонкурентном рынке API-шлюзов продолжают эту тенденцию, добавляя функции, с помощью которых они пытаются дифференцировать свои продукты. Это приводит к появлению чрезмерных продуктов API-шлюзов, чья функциональность — помимо того, что по сути является обратным прокси-сервером — поощряет проекты, которые по-прежнему сложно тестировать и развертывать. Шлюзы API действительно полезны при решении некоторых конкретных задач, таких как проверка подлинности и ограничение скорости, но любые смарт-домены должны находиться в приложениях или службах. https://www.thoughtworks.com/radar/platforms/overambitious-api-gateways

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

15. Микросервисные API шлюзы и агрегаторы — выводы

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

16. Что дальше

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