Пакетная обработка запросов с использованием API Gateway

Bobur Umurzokov

Bobur Umurzokov

April 27, 2023

Technology

Пакетная обработка запросов — это мощная техника, используемая в веб-разработке для повышения производительности API. Она позволяет разработчикам объединять несколько API-запросов в один цикл HTTP-запроса/ответа. Другими словами, один API-запрос от клиента может быть преобразован в несколько API-запросов к набору серверов бэкенда, а ответы агрегируются в один ответ клиенту. Это может значительно сократить количество циклов обмена данными между клиентом и сервером.

В этой статье мы рассмотрим, как реализовать пакетную обработку запросов в Apache APISIX, а также рассмотрим некоторые сценарии, где это может быть полезно.

Это похоже на шаблон API Composition, который широко применяется в архитектуре микросервисов.

Пакетная обработка запросов vs множественные API-вызовы

Зачем использовать пакетную обработку запросов?

Когда клиент отправляет несколько API-запросов на сервер, каждый запрос требует отдельного цикла HTTP-запроса/ответа. Это может привести к увеличению задержки, снижению производительности и увеличению нагрузки на сервер. Группируя несколько запросов в один пакетный запрос, можно сократить количество циклов HTTP-запроса/ответа, что приведет к повышению производительности и снижению задержки.

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

  • Получение нескольких записей из базы данных
  • Обновление нескольких записей в базе данных
  • Выполнение нескольких API-запросов для завершения задачи

Реальные примеры пакетной обработки запросов

Пример 1:

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

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

Социальное медиа-приложение, отображающее ленту пользователя

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

Пример 2:

Другой пример: у вас есть мобильное приложение, которое отображает список продуктов для просмотра пользователями. Чтобы заполнить этот список, необходимо выполнить несколько API-запросов для получения данных о продуктах с удаленного сервера, таких как:

  • Получение списка идентификаторов продуктов.
  • Для каждого идентификатора продукта получение деталей продукта (название, описание, изображение и т.д.).

Пример 3:

Представьте, что у вас есть веб-приложение для управления конференциями, где в системе есть несколько спикеров, и вы хотите отобразить сессии и связанные темы спикера на одной веб-странице. Бэкенд-сервис Conference API имеет два разных эндпоинта /speaker/{speakerId}/sessions и /speaker/{speakerId}/topics, чтобы предоставить эту информацию. Чтобы показать как сессии, так и темы, относящиеся к одному спикеру, вы можете отправить два запроса из фронтенд-приложения, что не является идеальным решением. Вместо этого вы можете использовать API Gateway, чтобы объединить все эти запросы в один HTTP-запрос, как объясняется в следующем разделе.

Пакетная обработка запросов с использованием API Gateway

Пакетная обработка запросов с использованием API Gateway Apache APISIX

Для реализации пакетной обработки запросов в APISIX можно использовать плагин batch-requests. Этот плагин позволяет определить набор API-запросов в одном теле HTTP POST запроса. Каждый запрос может иметь свой HTTP-метод, путь URL, набор заголовков и тело запроса. Пример команды curl для примера 3 (запросы к Conference API):

curl -i http://{API_GATEWAY_HOST_ADDRESS}/speaker -X POST -d \ '{ "pipeline": [ { "method": "GET", "path": "/speaker/1/topics" }, { "method": "GET", "path": "/speaker/1/sessions" } ] }'

Когда APISIX получает пакетный запрос, плагин batch-requests разбирает тело запроса и выполняет каждый запрос в пакете параллельно. Плагин также агрегирует ответы от каждого запроса и возвращает их в одном HTTP-ответе клиенту. См. следующий раздел демонстрации, чтобы узнать, как достичь этого шаг за шагом.

Демонстрация плагина batch-requests

Прежде чем использовать плагин batch-requests, необходимо установить Apache APISIX.

Предварительные требования

  • Docker используется для установки контейнеризованного etcd и APISIX.
  • curl используется для отправки запросов к Admin API APISIX. Вы также можете использовать удобные инструменты, такие как Postman, для взаимодействия с API.

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

curl -sL <https://run.api7.ai/apisix/quickstart> | sh

Настройка бэкенд-сервиса (upstream)

Необходимо настроить бэкенд-сервис для Conference API, на который будут перенаправляться запросы. Это можно сделать, добавив upstream-сервер в Apache APISIX через Admin API.

curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -X PUT -d ' { "name": "Conferences API upstream", "desc": "Register Conferences API as the upstream", "type": "roundrobin", "scheme": "https", "nodes": { "conferenceapi.azurewebsites.net:443": 1 } }'

Создание маршрута для API пакетной обработки

Необходимо создать новый маршрут, который перехватывает запросы к /speaker и предоставляет публичный виртуальный эндпоинт для пакетной обработки с использованием плагина [public-api](https://apisix.apache.org/docs/apisix/plugins/public-api/).

curl http://127.0.0.1:9180/apisix/admin/routes/a -X PUT -d ' { "uri": "/speaker", "plugins": { "public-api": { "uri": "/apisix/batch-requests" } } }'

Создание маршрута для эндпоинтов тем и сессий спикера

Далее создаем еще один маршрут для эндпоинтов тем и сессий спикера (/speaker/*/topics и /speaker/*/topics), чтобы отдельные запросы, извлеченные API Gateway из пакетных запросов для получения тем или сессий спикера, перенаправлялись на соответствующие эндпоинты Conference API, и мы ссылаемся на существующий upstream-сервис.

curl http://127.0.0.1:9180/apisix/admin/routes/b -X PUT -d ' { "methods": ["GET"], "uris": ["/speaker/*/topics","/speaker/*/sessions"], "plugins": { "proxy-rewrite":{ "host":"conferenceapi.azurewebsites.net" } }, "upstream_id":"1" }'

Вы можете заметить, что мы используем еще один плагин proxy-rewrite и явно указываем адрес хоста для Conference API. В противном случае API Gateway может выполнить преобразование DNS и запросить Conference API по его IP-адресу.

Тестирование пакетной обработки запросов

Вот пример использования плагина batch-requests в APISIX:

curl -i http://127.0.0.1:9080/speaker -X POST -d \ '{ "pipeline": [ { "method": "GET", "path": "/speaker/1/topics" }, { "method": "GET", "path": "/speaker/1/sessions" } ] }'

В этом примере маршрут определен для эндпоинта /speaker, который поддерживает пакетную обработку запросов через плагин batch-requests. Плагин настроен с набором из двух запросов, каждый из которых получает запись спикера по идентификатору с темами и сессиями. Если вы выполните эту команду, вы получите объединенный ответ от API Gateway:

[ { "body":"{\r\n \"collection\": {\r\n \"version\": \"1.0\",\r\n \"links\": [],\r\n \"items\": [\r\n {\r\n \"href\": \"https://conferenceapi.azurewebsites.net/topic/8\",\r\n \"data\": [\r\n {\r\n \"name\": \"Title\",\r\n \"value\": \"Microsoft\"\r\n }\r\n ],\r\n \"links\": [\r\n {\r\n \"rel\": \"http://tavis.net/rels/sessions\",\r\n \"href\": \"https://conferenceapi.azurewebsites.net/topic/8/sessions\"\r\n }\r\n ]\r\n },\r\n {\r\n \"href\": \"https://conferenceapi.azurewebsites.net/topic/10\",\r\n \"data\": [\r\n {\r\n \"name\": \"Title\",\r\n \"value\": \"Mobile\"\r\n }\r\n ],\r\n \"links\": [\r\n {\r\n \"rel\": \"http://tavis.net/rels/sessions\",\r\n \"href\": \"https://conferenceapi.azurewebsites.net/topic/10/sessions\"\r\n }\r\n ]\r\n }\r\n ],\r\n \"queries\": [],\r\n \"template\": {\r\n \"data\": []\r\n }\r\n }\r\n}", "status":200, "headers":{ "Expires":"-1", "Connection":"keep-alive", "Pragma":"no-cache", "Content-Length":"953", "Server":"APISIX/3.2.0", "Content-Type":"application/vnd.collection+json", "X-AspNet-Version":"4.0.30319", "Cache-Control":"no-cache", "X-Powered-By":"ASP.NET" }, "reason":"OK" }, { "body":"{\r\n \"collection\": {\r\n \"version\": \"1.0\",\r\n \"links\": [],\r\n \"items\": [\r\n {\r\n \"href\": \"https://conferenceapi.azurewebsites.net/session/206\",\r\n \"data\": [\r\n {\r\n \"name\": \"Title\",\r\n \"value\": \"\\r\\n\\t\\t\\tjQuery Mobile and ASP.NET MVC\\r\\n\\t\\t\"\r\n },\r\n {\r\n \"name\": \"Timeslot\",\r\n \"value\": \"05 December 2013 09:00 - 10:00\"\r\n },\r\n {\r\n \"name\": \"Speaker\",\r\n \"value\": \"Scott Allen\"\r\n }\r\n ],\r\n \"links\": [\r\n {\r\n \"rel\": \"http://tavis.net/rels/speaker\",\r\n \"href\": \"https://conferenceapi.azurewebsites.net/speaker/16\"\r\n },\r\n {\r\n \"rel\": \"http://tavis.net/rels/topics\",\r\n \"href\": \"https://conferenceapi.azurewebsites.net/session/206/topics\"\r\n }\r\n ]\r\n }\r\n ],\r\n \"queries\": [],\r\n \"template\": {\r\n \"data\": []\r\n }\r\n }\r\n}", "status":200, "headers":{ "Expires":"-1", "Connection":"keep-alive", "Pragma":"no-cache", "Content-Length":"961", "Server":"APISIX/3.2.0", "Content-Type":"application/vnd.collection+json", "X-AspNet-Version":"4.0.30319", "Cache-Control":"no-cache", "X-Powered-By":"ASP.NET" }, "reason":"OK" } ]

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

Основные выводы

  • Пакетная обработка запросов с использованием API Gateway может быть полезной техникой для повышения производительности вашего API.
  • Apache APISIX предоставляет плагин batch-requests, который позволяет разработчикам легко реализовать пакетную обработку запросов.

Следующие шаги

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

Рекомендуемые материалы

Tags: