Раскрытие индивидуальных решений: использование Apache APISIX и Node-RED в гармонии
March 6, 2024
Предыстория
Многие пользователи Apache APISIX в корпоративных средах требуют кастомизации для удовлетворения специфических требований в определённых сценариях, несмотря на наличие множества мощных встроенных функций плагинов.
Пользователи часто выбирают написание плагинов на Lua и их подключение к экземплярам APISIX для использования. Однако аудитория Lua относительно ограничена. Хотя начать работать с ним легко, освоить его не так просто, и реализация сложной логики преобразования данных на Lua может стать довольно сложной. В настоящее время только часть хуков доступна для вызова разработчиками через Java Plugin Runner, что требует внесения изменений в исходный код Java Plugin Runner для функциональностей, которые не поддерживаются напрямую.
На диаграмме ниже показаны три распространённых шаблона использования плагинов: плагины Lua, работающие непосредственно в ядре APISIX; Plugin Runner, взаимодействующий через RPC с плагинами на языках Java, Golang и т.д.; и плагины WASM, которые преобразуются в байт-код и выполняются внутри ядра APISIX.

Из отзывов пользователей стало ясно, что необходимость в кастомных плагинах часто связана с преобразованием данных, таких как параметры HTTP-запросов и вызов внешних API для обработки данных.
Для решения этой проблемы был предложен новый подход для расширения возможностей Apache APISIX. Этот подход предполагает использование только встроенных плагинов в Apache APISIX для настройки общих возможностей, таких как аутентификация и ограничение скорости, при этом размещая новую кастомную логику во внешних сервисах. Внешний сервис может быть либо бинарной программой, либо другим API-сервисом, который будет рассматриваться как апстрим для APISIX. Этот внешний сервис будет обрабатывать запросы и ответы как промежуточное ПО. Этот подход также может быть применён к другим API-шлюзам или прокси-сервисам.
Описание сценария
У нас есть ряд сервисов, предоставляющих услуги по запросу данных на стороне апстрима (в этой статье используется https://api-ninjas.com/api в качестве примера). Например, можно получить последнюю информацию о погоде и информацию о стране (например, ВВП страны, название столицы и единица валюты) на основе названия города.
Наша основная цель — предоставить разработчикам универсальный интерфейс запроса, при этом всё ещё имея возможность определять содержание данных, которые они хотят получить, на основе названия города и параметров области данных. Кроме того, чтобы защитить апстрим-сервисы от злоупотреблений, мы должны добавить сервис аутентификации к интерфейсу разработчика, позволяя только запросам с правильным API Key быть переадресованными на апстрим-сервис.
Анализ проблемы
До внедрения Node-Red для удовлетворения вышеуказанных требований разработчики APISIX рассматривали использование плагинов Lua. Хотя Apache APISIX предоставляет подробную документацию по разработке плагинов, бизнес-разработчикам необходимо изучить синтаксис Lua и методы оптимизации, понять различные хуки запросов, предоставляемые APISIX, и постоянно перезагружать плагины для проверки при написании логики для извлечения и проверки параметров. После завершения тестирования им также необходимо упаковать плагины Lua в программу APISIX или распространить их на все экземпляры APISIX для подключения.
Пример требований, который мы предоставляем в этом блоге, включает в себя анализ определённых параметров из клиентских запросов, а затем построение запросов для получения данных из различных апстрим-сервисов. Однако мы потратили много времени на обработку транзакций, не связанных с написанием бизнес-логики. Поэтому для такой логики, связанной с преобразованием параметров, форматов или внешними вызовами, мы можем использовать более лёгкий и интуитивно понятный подход, который как раз и решает проблему, с которой справляется Node-Red.
Введение в Node-Red
Node-RED — это мощный и простой в использовании инструмент для потокового программирования, подходящий для задач автоматизации и обработки потоков данных в различных областях. Его интерфейс программирования, богатая библиотека узлов и гибкая расширяемость позволяют нам быстро строить сложные потоки и реализовывать различные сценарии применения. Вот некоторые из узлов, предоставляемых Node-RED:
-
Узел HTTP_IN: Предоставляет конечную точку для вызова внешних сервисов, которую мы будем использовать как апстрим-сервис для APISIX.
-
Узел Function: Позволяет разработчикам писать функции на JavaScript для изменения, удаления и т.д. входных/выходных данных.
-
Узел Switch: Позволяет разработчикам задать набор условий для перехода к следующему указанному узлу при выполнении условия.
-
Узел HTTP_Request: Может устанавливать URL и т.д., чтобы отправлять данные на эту конечную точку через Node-RED при выполнении всего рабочего процесса.
-
Узел Change: Может добавлять, изменять или удалять указанные значения указанного объекта.
-
Узел HTTP_Response: Используется для возврата ответов клиентам.
Помимо перечисленных выше узлов, Node-RED также предоставляет множество других встроенных узлов. В этой статье мы покажем читателям, как реализовать вышеуказанные требования с помощью Node-RED.
Пример демонстрации
Настройка окружения
Мы развернём необходимые компоненты через контейнеризацию, используя DigitalOcean Droplet в качестве серверного ресурса.
$ doctl compute ssh-key list ID Name FingerPrint 25621060 Zhiyuan Ju 2c:84:b7:d8:14:0a:a0:0f:ca:fe:ca:24:06:a4:fe:39 $ doctl compute droplet create \ --image docker-20-04 \ --size s-2vcpu-4gb-amd \ --region sgp1 \ --vpc-uuid 646cf2b8-03d8-4f48-b7c8-57cdee60ad27 \ --ssh-keys 25621060 \ apisix-nodered-docker-ubuntu-s-2vcpu-4gb-amd-sgp1-01 $ doctl compute droplet list ID Name Public IPv4 Private IPv4 Public IPv6 Memory VCPUs Disk Region Image VPC UUID Status Tags Features Volumes 404094941 apisix-nodered-docker-ubuntu-s-2vcpu-4gb-amd-sgp1-01 143.198.192.64 10.104.0.3 4096 2 80 sgp1 Ubuntu Docker 25.0.3 on Ubuntu 22.04 646cf2b8-03d8-4f48-b7c8-57cdee60ad27 active droplet_agent,private_networking
Развёртывание Apache APISIX
Мы используем APISIX Quickstart для запуска нового экземпляра APISIX. Подробную документацию можно найти по ссылке https://docs.api7.ai/apisix/getting-started/.
$ curl -sL https://run.api7.ai/apisix/quickstart | sh
Развёртывание Node-RED
Node-RED предоставляет несколько методов развёртывания, и мы быстро развернём его через Docker и интегрируем с существующим окружением. Подробнее о развёртывании можно узнать в официальной документации: https://nodered.org/docs/getting-started/.
При развёртывании Node-RED убедитесь, что контейнер добавлен в сеть APISIX, чтобы он мог взаимодействовать с APISIX и обрабатывать запросы.
$ docker run -d -it -p 1880:1880 -v $PWD/configs/nodered/data:/data --network=apisix-quickstart-net --name mynodered -u Node-Red:dialout nodered/Node-Red
Настройка Node-RED
- Для обработки запросов, поступающих в Node-RED из APISIX, Node-Red должен проверить, существуют ли параметры в запросе и являются ли они допустимыми. Если параметры отсутствуют или недействительны, будет возвращено сообщение об ошибке. Если они действительны, будет выполнен следующий узел. В этом конкретном сценарии мы разрешаем запросы данных только для двух городов: Стокгольм (city=stockholm) и Берлин (city=berlin).

- Как только запрос переходит к следующему узлу, Node-RED должен определить тип запрашиваемых данных. В этом сценарии есть три типа: информация о погоде (
scope=weather), информация о стране, в которой находится город (scope=country), и ВВП страны, в которой находится город (scope=gdp).

- Если оба параметра
CityиScopeдействительны, Node-RED определит, из какого API получать данные, на основе значения scope. После установки URL, Method, Payload, X-API-Key и т.д., узел Node-RED будет обращаться к соответствующей конечной точке для получения данных при срабатывании.

- При получении данных для
scope=gdp, Node-RED должен извлечь значение ВВП из тела ответа внешнего API. Это можно сделать с помощью узла Change для извлечения или узла Function.

- Наконец, Node-RED вернёт обработанные данные в APISIX, который передаст их клиенту. Итоговая диаграмма Node-RED показана ниже.

Создание маршрутов APISIX
Чтобы сделать сервис Node-Red доступным для клиентов, нам нужно использовать APISIX в качестве обратного прокси для конечных точек, предоставляемых Node-Red. Вот шаги, которые необходимо выполнить:
-
Создайте маршрут APISIX и установите
mynodered:1880в качестве апстрима для этого маршрута. Таким образом, все запросы, отправленные на эту конечную точку, будут перенаправлены на сервис Node-Red. -
Включите аутентификацию по ключу, чтобы гарантировать, что только запросы с действительным API Key смогут пройти аутентификацию и получить доступ к сервису Node-Red.
Следуя этим шагам, мы можем безопасно предоставить сервис Node-Red клиентам и гарантировать, что только авторизованные пользователи смогут получить к нему доступ.
$ curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT -d ' { "id": "proxy-global-data-endpoint", "uri": "/global-data", "upstream": { "type": "roundrobin", "nodes": { "mynodered:1880": 1 } }, "plugins": { "key-auth": {} } }' $ curl -i "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT -d ' { "username": "tom", "plugins": { "key-auth": { "key": "secret-key" } } }'
Проверка запросов
Мы попробуем несколько сценариев, чтобы убедиться, что APISIX и Node-Red работают как ожидается:
Сценарий 1
-
Описание сценария: Доступ к API с неправильным ключом.
-
Ожидаемый результат: Поскольку предоставленный API Key неверен, запрос должен быть отклонён, и должно быть возвращено соответствующее сообщение об ошибке.
$ curl http://143.198.192.64:9080/global-data -H "apikey: invalid-key" -i HTTP/1.1 401 Unauthorized Date: Mon, 04 Mar 2024 07:47:24 GMT Content-Type: text/plain; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Server: APISIX/3.8.0 {"message":"Invalid API key in request"}
Сценарий 2
-
Описание сценария: Доступ к API с правильным ключом, но с недействительным полем
City. -
Ожидаемый результат: Поскольку параметры запроса не соответствуют требованиям, должно быть возвращено соответствующее сообщение об ошибке, указывающее, что поле
Cityнедействительно.
$ curl "http://143.198.192.64:9080/global-data?city=singapore&scope=country" -H "apikey: secret-key" -i HTTP/1.1 400 Bad Request Content-Type: application/json; charset=utf-8 Content-Length: 69 Connection: keep-alive Access-Control-Allow-Origin: * X-Content-Type-Options: nosniff ETag: W/"45-IOhgB2XkDHi2Kt4PP42n1xa8Gys" Date: Mon, 04 Mar 2024 07:48:02 GMT Server: APISIX/3.8.0 {"errorCode":400,"message":"Allowed city Options: Stockholm, Berlin"}
Сценарий 3
-
Описание сценария: Доступ к API с правильным ключом и действительными полями
CityиScopeдля получения данных о стране. -
Ожидаемый результат: Запрос должен быть успешным, и должна быть возвращена соответствующая информация о стране, в которой находится
City.
$ curl "http://143.198.192.64:9080/global-data?city=stockholm&scope=country" -H "apikey: secret-key" -i HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Content-Length: 947 Connection: keep-alive Access-Control-Allow-Origin: * X-Content-Type-Options: nosniff ETag: W/"3b3-XDlm9OHfuUrWH+g42q8L1F2uu/o" Date: Mon, 04 Mar 2024 07:48:26 GMT Server: APISIX/3.8.0 [{"gdp":556086,"sex_ratio":100.4,"surface_area":438574,"life_expectancy_male":80.8,"unemployment":6.7,"imports":158710,"homicide_rate":1.1,"currency":{"code":"SEK","name":"Swedish Krona"},"iso2":"SE","employment_services":80.7,"employment_industry":17.7,"urban_population_growth":1.1,"secondary_school_enrollment_female":157.9,"employment_agriculture":1.6,"capital":"Stockholm","co2_emissions":37.6,"forested_area":68.9,"tourists":7440,"exports":160538,"life_expectancy_female":84.4,"post_secondary_enrollment_female":82.1,"post_secondary_enrollment_male":52.7,"primary_school_enrollment_female":127.4,"infant_mortality":2,"gdp_growth":2.2,"threatened_species":98,"population":10099,"urban_population":87.7,"secondary_school_enrollment_male":148.1,"name":"Sweden","pop_growth":0.7,"region":"Northern Europe","pop_density":24.6,"internet_users":92.1,"gdp_per_capita":55766.8,"fertility":1.8,"refugees":310.4,"primary_school_enrollment_male":125.8}]
Сценарий 4
-
Описание сценария: Доступ к API с правильным ключом и действительными полями
CityиScopeдля получения данных о ВВП. -
Ожидаемый результат: Запрос должен быть успешным, и должны быть возвращены данные о ВВП страны, в которой находится
City.
$ curl "http://143.198.192.64:9080/global-data?city=stockholm&scope=gdp" -H "apikey: secret-key" -i HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 6 Connection: keep-alive Access-Control-Allow-Origin: * ETag: W/"6-j8I5kokycgWjCeKC1c2UfJW7AQY" Date: Mon, 04 Mar 2024 07:48:48 GMT Server: APISIX/3.8.0 556086
Проверив эти четыре сценария, мы можем подтвердить, что APISIX и Node-Red работают как ожидается и могут корректно обрабатывать различные типы запросов.
Итог
Мы предоставляем новый подход для более умного решения проблемы разработки кастомных возможностей, продемонстрированный на подробном примере.
-
Маршрутизация запросов API и проверка идентификации: Сначала, используя функциональность маршрутизации и плагины аутентификации Apache APISIX, APISIX перенаправляет клиентские запросы на сервис Node-Red, если предоставленные учётные данные действительны.
-
Обработка и преобразование запросов: В Node-Red мы создаём поток для обработки входящих API-запросов. Используя узел HTTP input для получения запросов от APISIX, мы анализируем и проверяем параметры запроса, чтобы убедиться, что они соответствуют бизнес-требованиям.
-
Обработка бизнес-логики: Как только получен действительный запрос, мы можем выполнить бизнес-логику в Node-Red. Например, отправка запросов на различные бизнес-API на основе параметров для получения данных и извлечение необходимых полей из ответа. После завершения этих операций окончательные данные возвращаются в APISIX.
-
Обработка ошибок и логирование: В процессе обработки, если возникают ошибки или исключения, мы можем добавить узлы обработки ошибок в Node-Red для захвата и обработки исключительных ситуаций. Кроме того, мы можем использовать узлы логирования для записи ключевой информации в процессе обработки для последующего устранения неполадок и анализа, что не показано в этом примере.
Комбинируя APISIX и Node-Red, мы можем визуально реализовать полный процесс обработки запросов, включая маршрутизацию запросов, обработку данных, бизнес-логику и т.д., без необходимости написания сложного кода или плагинов. Этот гибкий и настраиваемый подход помогает нам быстрее строить и настраивать функциональность системы, повышать эффективность разработки, снижать затраты на разработку и обеспечивать стабильность и масштабируемость системы.