step functions でApi Gatewayのタイムアウト問題を解決

この記事は2023年12月アドベントカレンダー8日目の記事になっています。

今回行ったのは、API Gatewayを利用し「Lambda関数でOpenAIのAPIをコールできる」APIを作成することです。

初めに

今回行った流れは、1を作り1では問題がありうまくいかなかったので2に変更しています。

  1. API GatewayからlambdaにPOSTをして、lambdaからOpenAIのAPIを投げレスポンスを受け取る
  2. step functionsを使いOpenAIのAPIを投げるlambdaの実行をするフローを作りそのフローを作動させるAPIと結果を受け取るAPIの二つを作成する


1から2に変更した理由はAPI Gatewayのタイムアウトによりレスポンスの受取ができなかったからです。

今回作成したアーキテクチャ

1のアーキテクチャ

2のアーキテクチャ

API Gatewayとlambdaの間にstep functionsが入る

step functionsはそもそも何ができる?

step functionsはアプリケーションのワークフローを一連のイベント駆動型ステップとして確認できます。
Step Functions で、LambdaなどのAWS のサービスを呼び出すことができます。
機械学習モデルを処理してパブリッシュするワークフローを作成できます。
抽出、変換、ロード (ETL) ワークフローを作成するため、AWS Glue など、Step Functions コントロール AWS のサービスを利用できます。
また、手動による介入が必要なアプリケーション用に実行時間が長い自動化されたワークフローを作成することもできます。               (AWSドキュメントより抜粋)

step finctionsについて詳しく
https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/welcome.html

実際にやったこと

まず各リソースの作成を行いました。(リソースに対するiam roleの作成もしていますが省略します)

lambda関数の作成
このlambda関数はOpenAIのAPIをコールし、レスポンスを受け取るためのものです。

lambda関数を実行するためのAPI Gatewayリソースとメソッドの作成
統合タイプはlambda統合、メソッドはPOSTで、統合レスポンスのマッピングテンプレートはフロントから渡されたものをjsonに変換してlambdaに渡します。(lambdaはjsonしか扱えないため)

統合リクエストのマッピングテンプレート


CORSの設定
CORSを有効にしていないとアクセスが許可されずはじかれてしまうので有効にします。
CORSについて
https://aws.amazon.com/jp/what-is/cross-origin-resource-sharing/

1のアーキテクチャーのテスト
フロントから作成したAPIをfetchでPOSTする
レスポンスが返ってこない問題発生!)
API Gatewayがタイムアウトしている(デフォルトで設定されている29秒が最大)
lambdaの実行に時間がかかり、間に合っていない(原因特定)

2にアーキテクチャーを変更
lambda関数はそのまま使えるので据え置き

step functionsの作成
ステートマシンの作成を行いlambdaの実行をするフローを作成します。

lmabdaを動かすフロー


API Gatewayの変更・作成
今回は二つのAPIを作成します
step functionsを作動させるAPIに先ほど作ったAPIを変更します。
統合タイプはAWS統合、HTTP メソッドはPOST、アクションはStartExectionにする必要があります。

アクション名はStartExecution固定

また、マッピングテンプレートには

{
"stateMachineArn": "step functionsのstateMachineArn"
}


上記のようなステートマシンを特定するためのArnを設定する必要があります。

次にstep functionsの実行が終わっているかどうかを見に行き、終わっていたら結果を受け取るAPIを作成します。
こちらも統合タイプはAWS統合、HTTP メソッドはPOST、アクションはDescribeExecutionにする必要があります。

アクション名はDescribeExecution固定


2のアーキテクチャーのテスト
1.まず作成したステートマシンの起動をするAPIをフロントからPOSTする
2.ステートマシンから実行Arnと呼ばれる実行に対して一意の識別子のようなものが返ってくる
3.その実行Arnを持たせて今度は実行終了しているか確認するAPIを投げる
4.終わっていたらSOCCEEDかFAILDが返ってくるor実行中ならRUNNINGが返ってくる

成功!
フロントでレスポンス(ChatGPTの生成したテキスト)を受け取ることができた!

詰まった点

  • API Gatewayのマッピングテンプレートでlambdaに渡すときにjson形式じゃないとエラーを返してくること
  • CORSの有効化をしていないとアクセスできなかったこと
  • ステートマシンの作成時にログをとろうとしたができず、結局ログをとることはあきらめた(おそらくCloudWatch側にも許可が必要だった)

感想

私はAWSを本格的に触ったのが今回が初めてのことだったので、作ったアーキテクチャも複雑なものではなかったのですが、リソースの作成などにも手間取ってしまったりいろいろな問題にぶつかりました。
その都度調べたり教えてもらったりをして、少しAWSのことを知ることができよかったです。
また、エラーメッセージをしっかり読みどこが問題なのかを理解する力が必要だと思いました。