PythonのWebアプリケーション、DjangoやFlaskなどいろんなフレームワークがありますが、最近だとASGIをサポートしたFastAPIの採用例も増えているんじゃないでしょうか?
そんなFastAPIで作ったアプリをサーバレスにデプロイして運用できたら素敵ですよね。
そこで今回はFastAPIで作ったASGIアプリケーションをMangumでラップしてAWS Lambda + API Gatewayで動かしてみようと思います。
WSGIとASGIについて
DjangoやFlaskなど従来からあるPythonのWebアプリケーションフレームワークは、WSGI
(Web Server Gateway Interface) という同期インターフェースで作られています。
WebサーバーのGunicornやApacheなどで運用されたり、Lambdaで動かすServerless Frameworkのserverless-wsgiなどがあります。
FastAPIなどの最近のWebアプリケーションフレームワークでは、ASGI
(Asynchronous Server Gateway Interface) という非同期インターフェースで作られたりサポートされるようになりました。
非同期関数のインターフェースを取り、アプリケーションサーバのUvicornなどで運用されたりします。
Mangumについて
Mangum
(https://mangum.io/) とは、ASGIアプリケーションをAWS Lambdaで動かすためのアダプタです。
FastAPIなどで実装したASGIアプリケーションを、Lambda + API Gateway構成でサーバレスにWebアプリケーションとして動かす事ができます。
※最近Lambda + ALB構成のサポートもリリースされましたが、まだ安定していません。
サンプルアプリケーション
FastAPIでアプリケーションを作成します。
下記はAPIサーバーアプリを例にしていますが、htmlやtextを返したりバイナリファイルを返すようなアプリケーションでもokです。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"Hello": "World"}
Lambdaハンドラ
上記のASGIアプリケーションをMangumでラップする事で、Lambdaハンドラとして利用できるようになります。
from mangum import Mangum
from app import app
handler = Mangum(app)
デプロイ先のLambda関数でハンドラを lambda_handler.handler
に設定しておきます。
API Gateway
REST APIを作成し
/ ANY
/{proxy+} ANY
の2リソースを作成し、LAMBDA_PROXY
タイプの統合リクエスト設定でアプリケーションのLambdaに向けます。
これは全てのリクエストを投げてルーティングをLambda側で行うProxy設定です。
ステージをデプロイすれば
https://***.execute-api.ap-northeast-1.amazonaws.com/dev/
でFastAPIアプリケーションにアクセスできるようになりました。
余談: Lambdaで運用したら、せっかく非同期なASGIが同期的に実行されて意味ないのでは?
はい、まさにその通りです。LambdaでわざわざASGIを動かす事自体にメリットは余りありません。ServerlessFrameworkやChaliceなどの方が簡単でシンプルに運用できます。
が、ECSなどへの移植を視野に入れるとプロトタイプ、スモールスタートなプロダクトなどには有用と考えています。
アプリケーション部分は変更せずに移植が可能なため、リリース時やスケール時にASGIが活きてくるからです。くるはず。多分。きたらいいな。