Litestar と Mangum でサーバーレスAPIを作ってみた

Python の新しい ASGI フレームワーク Litestar で、サーバーレスAPI を作ってみました
2023.06.12

はじめに

みなさん、Litestar をご存知でしょうか?

豊富な機能を備えつつ、FastAPI や Starlette と比較して同等もしくはそれ以上に高速であるとドキュメントで紹介されている Python の新しい ASGI フレームワークです。

Hello World API を題材に FastAPI と軽く比較してみた記事は、こちら

そこで今回は Litestar と Mangum を組み合わせ、API Gateway + Lambda に環境を構築してみたいと思います。

事前準備

このレシピでは、Serverless Framework と Pipenv を利用します。同様に環境を構築する場合は、事前にセットアップしておきましょう。

環境構築

まずは、作業ディレクトリに移動して下記のコマンドを実行します。

$ pipenv --python 3.10
$ pipenv install litestar==2.0.0alpha7 mangum
$ mkdir src
$ touch serverless.yml src/main.py

ソースコードは、お好みのエディターで編集してください。 serverless.yml は、こんな感じ

serverless.yml

service: litestar-api
frameworkVersion: '3'

provider:
  name: aws
  runtime: python3.10
  architecture: arm64
  stage: dev
  region: ap-northeast-1

package:
  patterns:
    - '!**'
    - 'src/**'

functions:
  service:
    handler: src/main.handler
    events:
      - http:
          path: /{path+}
          method: ANY

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    dockerImage: public.ecr.aws/sam/build-python3.10:latest-arm64
    dockerizePip: true

main.py は、こんな感じです。

main.py

from litestar import Litestar, get
from mangum import Mangum


@get("/hello")
async def hello_world() -> dict[str, str]:
    """Handler function that returns a greeting dictionary."""
    return {"hello": "world"}


app = Litestar(route_handlers=[hello_world])
handler = Mangum(app, lifespan="off")

最後に、serverless-python-requirements プラグインをインストールしておきましょう。

$ sls plugin install -n serverless-python-requirements

ローカル環境で起動してみる

$ pipenv install -d uvicorn
$ pipenv shell
$ uvicorn src.main:app --reload --port 8080
INFO:     Will watch for changes in these directories: ['/Users/shimoda.yuji/Documents/GitHub/tmp/litestar']
INFO:     Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)
INFO:     Started reloader process [8084] using StatReload
INFO:     Started server process [8086]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

Litestar は、/schema/openapi.yaml/schema/openapi.json が自動生成され、Swagger-UI や Redoc だけでなく Stoplight Elements といった API ドキュメントが提供されています。

ブラウザを立ち上げて、http://localhost:8080/schema/elements にアクセスしてみます。

elements-640x349.png

デザインも整っていて、すごく見やすい API ドキュメントですね。

デプロイしてみる

では、AWS 環境にデプロイしてみましょう。

$ sls deploy --stage dev
Running "serverless" from node_modules

Deploying litestar-api to stage dev (ap-northeast-1)

✔ Service deployed to stack litestar-api-dev (126s)

endpoint: ANY - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/{path+}
functions:
  service: litestar-api-dev-service (11 MB)

デプロイが終わったら、API Gateway にリクエストを投げてみます。

$ curl -s https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello | jq .
{
  "hello": "world"
}

期待する動作が、確認できました。

さいごに

普段筆者は、サーバーレス(Lambda)構成の API を開発していますが AWS Lambda の料金は、リクエスト数やコードの実行時間に基づいた従量課金であるため より早く短い時間で処理できれば、コスト面でもメリットが生まれます。

(個人的に)Litestar は機能面だけでなく、性能面も含めて魅力を感じました。 公式ドキュメントもしっかりまとまっている雰囲気ですし、もう少し色々と触っていこうと思います。

ではでは