Apache APISIX Serverless Plugin 用于 Event Hooks

Bobur Umurzokov

Bobur Umurzokov

February 15, 2023

Technology

Apache APISIX は、Nginx 上に構築されたオープンソースの高性能な API ゲートウェイ です。その強力な機能の一つに、サーバーレス関数を作成する機能があります。サーバーレス関数は、Apache APISIX の機能を拡張するための小さなステートレスなプログラムです。この記事では、Apache APISIX の サーバーレス プラグイン の基本と、イベントに応じて サーバーレス関数 をトリガーする方法について説明します。

学習目標

この記事を通じて、以下の内容を学びます:

  • Apache APISIX サーバーレスプラグインとは何か?
  • サーバーレスプラグインの仕組みと使用方法
  • サーバーレスプラグインのユースケース
  • サーバーレスプラグインを使用して Webhook と統合する方法

Apache APISIX サーバーレスプラグインとは?

Apache APISIX の サーバーレス プラグインは、イベントフック用のサーバーレス関数を作成し、API ゲートウェイに統合することを可能にします。このプラグインは、イベントに応じてカスタムコードを実行するためのシンプルで柔軟な方法を提供し、基盤となるインフラストラクチャを管理する必要がありません。

サーバーレスプラグインは、イベント処理のロジックを個別のサーバーレス関数に分離することで、API アーキテクチャを簡素化し、管理を容易にします。Apache APISIX は、Azure FunctionsAWS Lambda などの主要なクラウドベンダーのサーバーレスフレームワークをサポートしています。

サーバーレスプラグインの使用方法

Apache APISIX のサーバーレスプラグインを使用するには、Lua プログラミング言語でサーバーレス関数コードを記述し、イベントに応じて実行したいロジックを実装します。その後、リクエスト-レスポンスサイクルのフェーズに応じて serverless-pre-function または serverless-post-function プラグインを有効にします。

現在、APISIX は Lua のみをサポートしています。他のプログラミング言語を使用したい場合は、プラグインランナー を使用して新しい カスタムプラグイン を作成することができます。

サーバーレスプラグインのユースケース

以下に、Apache APISIX サーバーレスプラグインのユースケースをいくつか紹介します:

  1. 動的ルーティング: サーバーレスプラグインを使用して、リクエストメソッド、URL パス、ヘッダー値などの特定の基準に基づいて、受信した API リクエストを動的にルーティングすることができます。これにより、基盤となる Apache APISIX の設定を変更することなく、複雑なルーティングシナリオを簡単に実装できます。

  2. 認証と認可: サーバーレスプラグインを使用して、API の認証と認可チェックを実装できます。例えば、リクエストヘッダーに有効な API キーが含まれていることを確認するサーバーレス関数を作成し、リクエストを続行する前にチェックすることができます。また、forward-auth プラグインと組み合わせて、外部認可サービスとして使用することもできます。

  3. リクエスト変換: サーバーレスプラグインを使用して、バックエンドサービスで処理される前に受信した API リクエストを変換することができます。例えば、バックエンドサービスが期待する形式にリクエストヘッダーやボディを変更するサーバーレス関数を作成できます。

  4. レスポンス変換: サーバーレスプラグインを使用して、バックエンドサービスからのレスポンスをクライアントに返す前に変換することもできます。例えば、クライアントが期待する形式にレスポンスヘッダーやボディを変更するサーバーレス関数を作成できます。

  5. ロギングとモニタリング: サーバーレスプラグインを使用して、API のロギングとモニタリングを実装できます。例えば、各 API リクエストの詳細情報(リクエストメソッド、URL、ヘッダー、ボディなど)をログに記録するサーバーレス関数を作成し、後で分析することができます。

Apache APISIX と Webhook の統合(デモ)

Apache APISIX を Webhook と統合するには、URL エンドポイントへの受信 POST リクエストをリッスンし、リクエストメソッドが POST であるかどうかを確認し、新しいメッセージが投稿されるたびにサードパーティサービスに Webhook 通知を送信するサーバーレス関数を作成する必要があります。

サーバーレス関数は、Webhook からのレスポンスも返す必要があります。これにより、Webhook のステータスやエラーメッセージを確認できます。どちらの場合も、APISIX はターゲットサービスと通信し、イベントがトリガーされたことを通知するために、指定された URL を呼び出します。

APISIX が Webhook に POST リクエストを送信

前提条件

  • APISIX を実行するために、マシンに Docker がインストールされていること。
  • RouteUpstreamPlugin などの APISIX のコアコンセプトに関する基本的な知識。

プロジェクトのセットアップ

まず、GitHub から apisix-docker プロジェクトリポジトリをクローンします:

git clone https://github.com/apache/apisix-docker.git

プロジェクトフォルダを好きなコードエディタで開きます。このチュートリアルでは VS Code を使用します。

Apache APISIX のインストールと実行

Apache APISIX を実行するには、以下の手順に従います:

新しいターミナルウィンドウを開き、プロジェクトのルートフォルダから docker compose up コマンドを実行します:

docker compose up -d

上記のコマンドは、Apache APISIX と etcd を Docker で一緒に実行します。

このデモでは Docker を使用して APISIX をインストールしましたが、インストールガイド には他のインストール方法も記載されています。

Apache APISIX でサーバーレス関数を設定する

Apache APISIX でサーバーレス関数を設定するには、エンドポイント用の新しい route を作成し、Lua で記述したカスタム関数コードを使用してサーバーレスプラグインを設定します。

以下は、エンドポイントへの受信 POST リクエストをリッスンし、Webhook 通知を送信する Lua でのサーバーレス関数の例です:

function webhook(conf, ctx)

    -- 必要なライブラリをインポート
    local http = require("resty.http")
    local core = require("apisix.core")

    -- リクエストメソッドが POST の場合のみ Webhook 通知を送信し、それ以外の場合は通常通りアップストリームに送信
    if core.request.get_method() == "POST" then
        -- 指定された URL に Webhook 通知を送信
        local httpc = http.new()
        local res, err = httpc:request_uri("http://webhook.site/9db3d3a0-ab64-4142-a39f-d4852ca50f8d", {
            method = "POST",
            headers = {
                ["Content-Type"] = "application/json"
            },
            body = core.request.get_body(),
        })
        -- Webhook からのレスポンスを確認
        if not res then
            core.log.error("Failed to send webhook: ", err)
            return 500, err
        end
    end

    -- アップストリームサービスからのレスポンスを返す
    return conf.status, conf.body
end

上記のサンプル Webhook 関数コードでは、クライアントから API ゲートウェイへのリクエストボディをペイロードとして、指定された URL に JSON POST リクエストを送信します。Webhook エンドポイントをモックするために、https://webhook.site を使用しています。

Webhook エンドポイントを作成して設定するには:

  1. Web ブラウザで https://webhook.site にアクセスし、URL を生成します。
  2. Your unique URL の横にある Copy to clipboard を選択します。
  3. 関数コードの HTTP リクエストの request_uri メソッドに貼り付けます。

また、POST 以外のリクエストもすべてアップストリームサービスに転送されます。次のステップで、ルートとアップストリームを設定します。

ルートとアップストリームの設定

次に、サーバーレス関数プラグインを有効にした新しいルートと、バックエンドサービスとして機能するアップストリームを作成します。

curl -X PUT 'http://127.0.0.1:9180/apisix/admin/routes/1' \
    -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
    -H 'Content-Type: application/json' \
    -d '{
    "uri": "/post",
    "plugins": {
        "serverless-pre-function": {
            "phase": "rewrite",
            "functions" : ["
                    return function(conf, ctx)
                        -- 必要なライブラリをインポート
                        local http = require(\"resty.http\")
                        local core = require(\"apisix.core\")

                        -- リクエストメソッドが POST の場合のみ Webhook 通知を送信し、それ以外の場合は通常通りアップストリームに送信
                        if core.request.get_method() == \"POST\" then
                            -- 指定された URL に Webhook 通知を送信
                            local httpc = http.new()
                            local res, err = httpc:request_uri(\"http://webhook.site/9db3d3a0-ab64-4142-a39f-d4852ca50f8d\", {
                                method = \"POST\",
                                headers = {
                                    [\"Content-Type\"] = \"application/json\"
                                },
                                body = core.request.get_body(),
                            })
                            -- Webhook からのレスポンスを確認
                            if not res then
                                core.log.error(\"Failed to send webhook: \", err)
                                return 500, err
                            end
                        end

                        -- アップストリームサービスからのレスポンスを返す
                        return conf.status, conf.body
                    end"]
        }
    },
    "upstream": {
        "nodes": {
            "httpbin.org:80": 1
        },
        "type": "roundrobin"
    }
}'

上記のルート設定例では、APISIX の Admin APIcurl リクエストを送信して最初のルートを作成しました。ルートリクエストボディでは、/post パスへのリクエストがサーバーレス関数コードをトリガーし、その後 httpbin.org に転送されることを指定しています。これは、リクエストメソッドが POST であるかどうかを確認し、イベントをサードパーティサービスの Webhook エンドポイントに送信するかどうかを判断した後、リクエストが httpbin.org/post エンドポイントにルーティングされることを意味します。バックエンドサービスは、あなたのバックエンドサービスに置き換えることができます。

また、serverless-pre-functionfunctions プロパティに関数コードを追加していることに気づくでしょう。

設定のテスト

最後に、/post API ゲートウェイエンドポイントを呼び出して、すべてが期待通りに動作し、POST イベントが Webhook サイトに送信されるかどうかをテストします。

curl -i http://127.0.0.1:9080/post -X POST -d \
'{
   "message": "A new webhook message"
}'

その後、前の手順で生成した Webhook URL にアクセスします。POST リクエストが表示され、イベントについて Webhook エンドポイントに通知され、リクエストボディが送信されているはずです。

APISIX が Webhook に送信したペイロード

さらに、モックアップストリームサービス httpbin.org からのレスポンスも返されます:

HTTP/1.1 200 OK
Content-Type: application/json

{
  ...
  "form": {
    "{\n   \"message\": \"A new webhook message\"\n}": ""
  },
  "headers": {
    "Accept": "*/*",
    "Content-Length": "41",
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "127.0.0.1",
    "X-Forwarded-Host": "127.0.0.1"
  },
  "json": null,
  "url": "http://127.0.0.1/post"
}

明らかに、POST 以外の HTTP リクエストを送信した場合、サーバーレス関数コードは Webhook エンドポイントをトリガーしません。

これは、Apache APISIX でサーバーレス関数を設定する基本的な例です。Webhook に応じて別の関数をトリガーするなど、サーバーレス関数にさらに複雑なロジックを追加することで、この機能を拡張できます。

結論

Apache APISIX のサーバーレスプラグインは、API リクエストの処理中に発生するイベントに応じてサーバーレス関数をトリガーするための柔軟でスケーラブルな方法を提供します。このプラグインを使用することで、API アーキテクチャを簡素化し、サービスのパフォーマンスと信頼性を向上させ、アプリケーションインフラストラクチャの管理コストを削減できます。

関連リソース

推奨コンテンツ

コミュニティ

🙋 Apache APISIX コミュニティに参加する 🐦 Twitter でフォローする 📝 Slack で見つける

Tags: