Leapcell: Python Webホスティング、非同期タスク、およびRedisのための最高のサーバレスプラットフォーム
FastAPI開発におけるASGIとUvicornの理解
FastAPIを使って開発する際、Uvicornサーバを使用する必要があります。初心者の方は、なぜそうなのか不思議に思うかもしれません。今日は、この疑問に答えましょう。
Uvicorn
まず、HTTPを使って簡単なHTTPリクエストを実装してみましょう:
import json
# ヘッダー内のバイトを文字列に変換するヘルパー関数を定義
def convert_bytes_to_str(data):
if isinstance(data, bytes):
return data.decode('utf-8')
if isinstance(data, tuple):
return tuple(convert_bytes_to_str(item) for item in data)
if isinstance(data, list):
return [convert_bytes_to_str(item) for item in data]
if isinstance(data, dict):
return {key: convert_bytes_to_str(value) for key, value in data.items()}
return data
async def app(scope, receive, send):
# print(scope)
data = convert_bytes_to_str(scope)
print(json.dumps(data, indent=4))
# リクエストのタイプをチェック
if scope['type'] == 'http':
# HTTPリクエストボディを待つ
event = await receive()
# レスポンスコンテンツ
response_body = json.dumps({"message": "Hello, ASGI!"}).encode('utf-8')
# HTTPレスポンスヘッダーを送信
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
(b'content-type', b'application/json'),
],
})
# HTTPレスポンスボディを送信
await send({
'type': 'http.response.body',
'body': response_body,
})
scope
フィールドにはバイナリ文字列が含まれているため、変換関数 convert_bytes_to_str
が必要です。簡単に分析してみましょう。リクエストパスやメソッドに関する情報は scope
の中にあります。scope
はHTTP以外のものもサポートしているため、現在のプロトコルのタイプを判断するために type
を使用する必要があります。そして、receive
関数を使ってリクエストボディを受け取ります。次に、json.dumps
を使ってレスポンスボディを作成し、encode
でエンコードします。最後に、リクエストヘッダーとリクエストボディを送信します。
ここでは、2回データを送信しています。この設計は非同期プログラミングの要件を満たし、異なるアプリケーションシナリオ(ストリーミングレスポンス)に対する処理能力を高めます。実際のプロジェクトの理解を深めることで、今では理論的な基礎からASGIを理解することができます。
ASGI
非同期サーバゲートウェイインターフェイス(Asynchronous Server Gateway Interface、ASGI)は、非同期Webアプリケーションを構築するためのPythonプロトコルです。
ASGIの主な機能
- 非同期サポート:非同期プログラミングを可能にします。
- マルチプロトコルサポート:WebSocketやロングポーリングなどのプロトコルをサポートしており、http/https/websocketをサポートします。
- 並列処理サポート:複数のリクエストを同時に処理できます。
- 通信:アプリケーションとサーバ、またアプリケーションの異なる部分同士が、メッセージの送受信により相互作用します。
ASGIプロトコルの構成
-
アプリケーションインターフェイス
- ASGIアプリケーションインターフェイスは、アプリケーションがASGIサーバとどのように相互作用するかを定義します。ASGIアプリケーションは、通常は非同期関数である呼び出し可能なオブジェクトで、2つのパラメータ
scope
とreceive
を受け取り、send
非同期ジェネレータを返します。- scope:リクエストに関する情報、例えばリクエストタイプ(HTTPまたはWebSocket)、パス、クエリ文字列、サーバ情報などを含む辞書です。
- receive:ASGIサーバからイベントを受け取るために使用される非同期呼び出しです。
- send:ASGIサーバにイベントを返すために使用される非同期ジェネレータです。
- ASGIアプリケーションインターフェイスは、アプリケーションがASGIサーバとどのように相互作用するかを定義します。ASGIアプリケーションは、通常は非同期関数である呼び出し可能なオブジェクトで、2つのパラメータ
-
サーバインターフェイス
- サーバインターフェイスの主な責務は以下の通りです:
- クライアントからの接続を受け付ける。
- 各接続に対して
scope
を作成する。 - アプリケーションの
receive
とsend
メソッドを呼び出してイベントを渡す。 - ネットワーク例外を処理し、接続を閉じる。
- サーバインターフェイスの主な責務は以下の通りです:
-
イベントループインターフェイス
- イベントループインターフェイスはASGIプロトコルの暗黙的な部分です。ASGIサーバによって管理され、ASGIプロトコルによって直接定義されるものではありません。
- イベントループは非同期タスクのスケジューリングと実行を担当し、これが非同期プログラミングの核心です。その主な機能は以下の通りです:
- 非同期タスクの実行とスケジューリング。
- ネットワークリクエストなどの非同期I/O操作の管理。
- コールバック関数と非同期ジェネレータの処理。
- ASGIでは、イベントループは通常以下のPythonライブラリによって提供されます:
- asyncio:Python標準ライブラリ内の非同期I/Oフレームワーク。
-
uvloop:
libuv
に基づく非同期イベントループで、Uvicornサーバとともによく使用されます。
ASGIサーバとアプリケーションは、イベントループに依存して非同期操作を実行し、多数の同時接続を効率的に処理できるようになります。
ASGIイベント
ASGIのイベント駆動型モデルは、ライフサイクル管理(起動とシャットダウン)、HTTPリクエストの処理、WebSocket接続管理を行います。異なる種類のイベントを通じて、開発者は接続とデータフローを正確に制御し、非同期および並列処理を実現できます。
-
ライフサイクルイベント
- ライフサイクルイベントは、ASGIアプリケーションの起動とシャットダウンサイクルに関連付けられています。通常、初期化とクリーンアップタスクを実行するために使用されます。
- lifespan.startup
- lifespan.shutdown
- ライフサイクルイベントは、ASGIアプリケーションの起動とシャットダウンサイクルに関連付けられています。通常、初期化とクリーンアップタスクを実行するために使用されます。
-
HTTPイベント
- ASGIによるHTTPリクエストの処理は、複数のイベントに分割され、各HTTPリクエストの詳細を管理できます。
- http.request
- http.response.start
- http.response.body
- http.disconnect
- websocket.send
- ASGIによるHTTPリクエストの処理は、複数のイベントに分割され、各HTTPリクエストの詳細を管理できます。
-
WebSocketイベント
- ASGIはWebSocket接続をサポートし、双方向通信を可能にします。
- websocket.connect
- websocket.receive
- ASGIはWebSocket接続をサポートし、双方向通信を可能にします。
ASGIライフサイクル
ASGIアプリケーションのライフサイクルとは、アプリケーションが起動とシャットダウンの間に経る段階を指します。これは、ライフサイクルイベントチャネルによって管理されます。
scope['type']: lifespan
-
message['type']
:起動とシャットダウンのメッセージ:lifespan.startup/lifespan.shutdown
- 送信タイプ:
{'type': 'lifespan.shutdown.complete'}
ASGIのライフサイクルは、アプリケーションの起動とシャットダウン、およびリクエストの確立、処理、応答、シャットダウンの2つの部分に分けられます。
Uvicornとアプリケーション層
前述のとおり、UvicornはASGIサーバ層を実装しています。しかし、アプリケーション層ではレベルが低すぎるため、あまり使いやすくありません。そのため、多くの上位レベルのフレームワークが登場しました:
- Starlette:高性能なWebサービスを構築するための軽量なASGIフレームワーク/ツールキット。FastAPIの基本コンポーネントであり、単独でも簡単なWebアプリケーションを作成することができます。
- FastAPI:APIを構築するための最新の高速(高性能)なWebフレームワークで、Python 3.6以降の型ヒントを使用します。Starletteと標準のPython型ヒントに基づいており、自動的なデータ検証とシリアル化、または対話型のAPIドキュメント生成を提供します。
ここでは他の点については詳細を述べる必要はありません。情報が多すぎると圧倒されるかもしれません。Uvicornは app
が必要なので、これら2つのフレームワークでは、インスタンス化されたオブジェクトが app
となります。そして、Uvicorn CLIを使ってアプリケーションを起動します:
uvicorn main:app --reload
まとめ
本記事では主にUvicornを通じてPythonのWeb ASGIプロトコルを探りました。ASGIはPythonの非同期サーバゲートウェイインターフェイスで、現代のPython Webプログラムの非同期、並列、マルチプロトコル機能を統合しています。
Leapcell: Python Webホスティング、非同期タスク、およびRedisのための最高のサーバレスプラットフォーム
最後に、Pythonプロジェクトのデプロイに最適なプラットフォームをおすすめします:Leapcell
1. マルチ言語サポート
- JavaScript、Python、Go、またはRustで開発できます。
2. 無料で無制限のプロジェクトをデプロイ
- 使用量に応じてのみ課金 — リクエストがなければ料金は発生しません。
3. 圧倒的なコスト効率
- 使い放題で、アイドル時の料金はかかりません。
- 例:25ドルで平均応答時間60msで694万回のリクエストをサポート。
4. シンプルな開発者体験
- 直感的なUIで簡単にセットアップできます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- アクション可能な洞察のためのリアルタイムメトリクスとログ。
5. 簡単なスケーラビリティと高性能
- 高い同時接続数を簡単に処理できる自動スケーリング。
- オペレーションオーバーヘッドはゼロ — 構築に集中できます。
Leapcell Twitter:https://x.com/LeapcellHQ