SAM CLIを使用してFast APIをローカルでテストしてみます。
■PC環境
>Windows 10
>sam –version
SAM CLI, version 1.52.0
>docker –version
Docker version 20.10.12, build e91ed57
>Python バージョン
Python 3.8.5
■アプリケーションのディレクトリを作成する
SAM CLIを使用してFast APIをローカルでテストしていきますので、まずはアプリケーションのディレクトリを作成します。
今回は「C:\Users\user_(フォルダパス)」内に「fastapi-on-lambda」というディレクトリを作成しました。
■FastAPIアプリケーションを作成する
ディレクトリを作成後、簡単なFastAPIアプリケーションを作成していきます。
■コード
from fastapi import FastAPI from mangum import Mangum app = FastAPI() @app.get("/") def get_root(): return {"message":"hello hello cq"} handler = Mangum(app)
今回は、LambdaのイベントペイロードとFastAPIの間のギャップを埋めるために、mangumと呼ばれるライブラリを使用します。このライブラリは、AWS API Gatewayから呼び出されるLambda内で動作するASGIアプリケーションのアダプタとして動作するものです。
このコードを「__init__.py」という名前で保存します。保存先は今回作成した「fastapi-on-lambda」というディレクトリ内に「src」というディレクトリを作り、さらに「app」というディレクトリを作り、この中が保存先となります。
■実行時の依存関係を指定する
保存後、関数を実行するためには、サードパーティの依存関係をいくつかインストールする必要がありますので、「requirements.txt」というファイルを作成します。
■requirements.txt
fastapi mangum
「requirements.txt」には、上記の2つの依存関係を記述し、保存します。なお、このファイルの保存先は、今回作成した「fastapi-on-lambda」というディレクトリ内の「src」が保存先となります。
■SAMテンプレートを作成する
保存後、今回はFast APIをローカルでテストするだけですが、AWS SAM CLIを使用してアプリケーションをデプロイすることも考え、リソースを定義するためにyaml形式でSAM templateを作成します。
■コード
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: FastAPI on Lambda Resources: Function: Type: AWS::Serverless::Function Properties: FunctionName: "FastAPILambda" CodeUri: src Handler: app.handler Runtime: python3.8 Events: Api: Type: HttpApi Properties: ApiId: !Ref Api Api: Type: AWS::Serverless::HttpApi Outputs: ApiUrl: Description: URL of your API Value: Fn::Sub: 'https://${Api}.execute-api.${AWS::Region}.${AWS::URLSuffix}/'
SAM templateの書き方や作成についてはこちら(https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html)が参考になります。なお、今回のtemplate(https://dev.to/aws-builders/deploy-fastapi-on-aws-part-1-lambda-api-gateway-1cp0)はこちらを参考していますが、修正を加えてあります。
修正としては「Resources:」の「Runtime: python3.8」と修正。python3.9でbuildすると、下記のようにbuildが失敗する。
Building codeuri: C:\Users\user_\fastapi-on-lambda\src runtime: python3.9 metadata: {} architecture: x86_64 functions: ['Function'] Build Failed Error: PythonPipBuilder:Validation - Binary validation failed for python, searched for python in following locations : ['C:\\Program Files (x86)\\Python37-32\\python.EXE', 'C:\\Program Files\\Python36\\python.EXE', 'C:\\Program Files\\Python38\\python.EXE', 'C:\\Users\\user_\\AppData\\Local\\Microsoft\\WindowsApps\\python.EXE'] which did not satisfy constraints for runtime: python3.9. Do you have python for runtime: python3.9 on your PATH?
失敗したので、今回のWindows10にインストールされている「python3.8」に変更しています。
さらに「Resources:」に「Timeout: 10」を追加しています。Lambda関数のデフォルトのタイムアウトは3秒(https://stackoverflow.com/questions/56182205/aws-lambda-function-timedout-after-3-sec-using-aws-sam)なので、今回はタイムアウトを「10」としています。これを追加せずに、buildを行い、ローカルでテストすると、下記のようにテストが失敗する。
Mounting Function at http://127.0.0.1:3000$default [X-AMAZON-APIGATEWAY-ANY-METHOD] You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template 2022-06-24 15:09:34 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit) Invoking app.handler (python3.8) Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.8:rapid-1.52.0-x86_64. Mounting C:\Users\user_\fastapi-on-lambda\.aws-sam\build\Function as /var/task:ro,delegated inside runtime container START RequestId: 9d3d38ed-1fea-46b1-b563-fd72fc4df540 Version: $LATEST Function 'Function' timed out after 3 seconds No response from invoke container for Function Invalid lambda response received: Lambda response must be valid json 2022-06-24 15:09:49 127.0.0.1 - - [24/Jun/2022 15:09:49] "GET / HTTP/1.1" 502 -
「No response from invoke container for Function」といったメッセージが出力され、またAPIが「{“message”:”Internal Server Error”}」を返してしまう。
これらの修正を加えて、「template.yaml」という名前で保存します。なお、保存先は「fastapi-on-lambda」ディレクトリが保存先となります。
■SAM CLIを使用してAPIをローカルでテストする
保存後、SAM CLI を使用してAPIをローカルでテストできるように、FastAPIアプリケーションをbuildします。buildのために、Windows10のコマンドプロンプトを起動します。
>cd fastapi-on-lambda
起動後、上記のコマンドを入力し、Enterキーを押します。cdコマンドで「fastapi-on-lambda」ディレクトリに移動します。
>sam build
移動後、上記のコマンドを入力し、Enterキーを押します。FastAPIアプリケーションをbuildします。
Building codeuri: C:\Users\user_\fastapi-on-lambda\src runtime: python3.8 metadata: {} architecture: x86_64 functions: ['Function'] Running PythonPipBuilder:ResolveDependencies Running PythonPipBuilder:CopySource Build Succeeded Built Artifacts : .aws-sam\build Built Template : .aws-sam\build\template.yaml Commands you can use next ========================= [*] Validate SAM template: sam validate [*] Invoke Function: sam local invoke [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch [*] Deploy: sam deploy --guided
Enterキーを押すと、「Build Succeeded」といったメッセージが出力されます。これでbuildが完了となります。
>sam local start-api
FastAPIアプリケーションの構築完了後、APIをローカルで開始します。開始するために、上記のコマンドを入力し、Enterキーを押します。
Mounting Function at http://127.0.0.1:3000$default [X-AMAZON-APIGATEWAY-ANY-METHOD] You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template 2022-06-25 11:53:50 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
Enterキーを押すと、上記のメッセージが出力されます。「Running on http://127.0.0.1:3000/」と出力されていますので、「http://127.0.0.1:3000/」のURLをコピーします。
>curl http://127.0.0.1:3000
コピー後、新しくコマンドプロンプトを起動します。起動後、上記のコマンドを入力し、Enterキーを押します。Windows10でcurlが標準で利用できるようになっているので、これを利用しテストします。
{"message":"hello hello cq"}
Enterキーを押すと、今回作成したFastAPIアプリケーションでreturnとして返されるメッセージが出力されました。これでテストは成功となります。
Mounting Function at http://127.0.0.1:3000$default [X-AMAZON-APIGATEWAY-ANY-METHOD] You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template 2022-06-25 11:53:50 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit) Invoking app.handler (python3.8) Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.8:rapid-1.52.0-x86_64. Mounting C:\Users\user_\fastapi-on-lambda\.aws-sam\build\Function as /var/task:ro,delegated inside runtime container START RequestId: 4c40f8a5-ded7-41e7-a9cf-97ad5496d802 Version: $LATEST END RequestId: 4c40f8a5-ded7-41e7-a9cf-97ad5496d802 REPORT RequestId: 4c40f8a5-ded7-41e7-a9cf-97ad5496d802 Init Duration: 0.12 ms Duration: 3719.03 ms Billed Duration: 3720 ms Memory Size: 128 MB Max Memory Used: 128 MB 2022-06-25 11:57:29 127.0.0.1 - - [25/Jun/2022 11:57:29] "GET / HTTP/1.1" 200 -
なお、「sam local start-api」でローカルHTTPサーバーを作成した方には、上記のようなメッセージが出力されていることが確認できました。
コメント