コンテンツにスキップ

Server Workers - Gunicorn と Uvicorn

前回のデプロイメントのコンセプトを振り返ってみましょう:

  • セキュリティ - HTTPS
  • 起動時の実行
  • 再起動
  • レプリケーション(実行中のプロセス数)
  • メモリ
  • 開始前の事前ステップ

ここまでのドキュメントのチュートリアルでは、おそらくUvicornのような**サーバープログラム**を**単一のプロセス**で実行しています。

アプリケーションをデプロイする際には、**複数のコア**を利用し、そしてより多くのリクエストを処理できるようにするために、プロセスの**レプリケーション**を持つことを望むでしょう。

前のチャプターであるデプロイメントのコンセプトにて見てきたように、有効な戦略がいくつかあります。

ここではGunicornが**Uvicornのワーカー・プロセス**を管理する場合の使い方について紹介していきます。

Info

DockerやKubernetesなどのコンテナを使用している場合は、次の章で詳しく説明します: コンテナ内のFastAPI - Docker

特に**Kubernetes**上で実行する場合は、おそらく**Gunicornを使用せず**、**コンテナごとに単一のUvicornプロセス**を実行することになりますが、それについてはこの章の後半で説明します。

GunicornによるUvicornのワーカー・プロセスの管理

Gunicorn**は**WSGI標準**のアプリケーションサーバーです。このことは、GunicornはFlaskやDjangoのようなアプリケーションにサービスを提供できることを意味します。Gunicornそれ自体は**FastAPI**と互換性がないですが、というのもFastAPIは最新のASGI 標準**を使用しているためです。

しかし、Gunicornは**プロセスマネージャー**として動作し、ユーザーが特定の**ワーカー・プロセスクラス**を使用するように指示することができます。するとGunicornはそのクラスを使い1つ以上の**ワーカー・プロセス**を開始します。

そして**Uvicorn**には**Gunicorn互換のワーカークラス**があります。

この組み合わせで、Gunicornは**プロセスマネージャー**として動作し、**ポート**と**IP**をリッスンします。そして、**Uvicornクラス**を実行しているワーカー・プロセスに通信を**転送**します。

そして、Gunicorn互換の**Uvicornワーカー**クラスが、FastAPIが使えるように、Gunicornから送られてきたデータをASGI標準に変換する役割を担います。

GunicornとUvicornをインストールする

$ pip install "uvicorn[standard]" gunicorn

---> 100%

これによりUvicornと(高性能を得るための)標準(standard)の追加パッケージとGunicornの両方がインストールされます。

UvicornのワーカーとともにGunicornを実行する

Gunicornを以下のように起動させることができます:

$ gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80

[19499] [INFO] Starting gunicorn 20.1.0
[19499] [INFO] Listening at: http://0.0.0.0:80 (19499)
[19499] [INFO] Using worker: uvicorn.workers.UvicornWorker
[19511] [INFO] Booting worker with pid: 19511
[19513] [INFO] Booting worker with pid: 19513
[19514] [INFO] Booting worker with pid: 19514
[19515] [INFO] Booting worker with pid: 19515
[19511] [INFO] Started server process [19511]
[19511] [INFO] Waiting for application startup.
[19511] [INFO] Application startup complete.
[19513] [INFO] Started server process [19513]
[19513] [INFO] Waiting for application startup.
[19513] [INFO] Application startup complete.
[19514] [INFO] Started server process [19514]
[19514] [INFO] Waiting for application startup.
[19514] [INFO] Application startup complete.
[19515] [INFO] Started server process [19515]
[19515] [INFO] Waiting for application startup.
[19515] [INFO] Application startup complete.

それぞれのオプションの意味を見てみましょう:

  • main:appmainは"main"という名前のPythonモジュール、つまりファイルmain.pyを意味します。そして appFastAPI アプリケーションの変数名です。

    • main:appはPythonのimport`文と同じようなものだと想像できます:

      from main import app
      
    • つまり、main:appのコロンは、from main import appのPythonのimportの部分と同じになります。

  • --workers: 使用するワーカー・プロセスの数で、それぞれがUvicornのワーカーを実行します。

  • --worker-class: ワーカー・プロセスで使用するGunicorn互換のワーカークラスです。

    • ここではGunicornがインポートして使用できるクラスを渡します:

      import uvicorn.workers.UvicornWorker
      
  • --bind: GunicornにリッスンするIPとポートを伝えます。コロン(:)でIPとポートを区切ります。

    • Uvicornを直接実行している場合は、--bind 0.0.0.0:80 (Gunicornのオプション)の代わりに、--host 0.0.0.0--port 80を使います。

出力では、各プロセスの**PID**(プロセスID)が表示されているのがわかります(単なる数字です)。

以下の通りです:

  • Gunicornの**プロセス・マネージャー**はPID 19499(あなたの場合は違う番号でしょう)で始まります。
  • 次に、Listening at: http://0.0.0.0:80を開始します。
  • それから uvicorn.workers.UvicornWorker でワーカークラスを使用することを検出します。
  • そして、**4つのワーカー**を起動します。それぞれのワーカーのPIDは、19511195131951419515です。

Gunicornはまた、ワーカーの数を維持するために必要であれば、**ダウンしたプロセス**を管理し、**新しいプロセスを**再起動**させます。そのため、上記のリストにある**再起動**の概念に一部役立ちます。

しかしながら、必要であればGunicornを**再起動**させ、**起動時に実行**させるなど、外部のコンポーネントを持たせることも必要かもしれません。

Uvicornとワーカー

Uvicornには複数の**ワーカー・プロセス**を起動し実行するオプションもあります。

とはいうものの、今のところUvicornのワーカー・プロセスを扱う機能はGunicornよりも制限されています。そのため、このレベル(Pythonレベル)でプロセスマネージャーを持ちたいのであれば、Gunicornをプロセスマネージャーとして使ってみた方が賢明かもしれないです。

どんな場合であれ、以下のように実行します:

$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
<font color="#A6E22E">INFO</font>:     Uvicorn running on <b>http://0.0.0.0:8080</b> (Press CTRL+C to quit)
<font color="#A6E22E">INFO</font>:     Started parent process [<font color="#A1EFE4"><b>27365</b></font>]
<font color="#A6E22E">INFO</font>:     Started server process [<font color="#A1EFE4">27368</font>]
<font color="#A6E22E">INFO</font>:     Waiting for application startup.
<font color="#A6E22E">INFO</font>:     Application startup complete.
<font color="#A6E22E">INFO</font>:     Started server process [<font color="#A1EFE4">27369</font>]
<font color="#A6E22E">INFO</font>:     Waiting for application startup.
<font color="#A6E22E">INFO</font>:     Application startup complete.
<font color="#A6E22E">INFO</font>:     Started server process [<font color="#A1EFE4">27370</font>]
<font color="#A6E22E">INFO</font>:     Waiting for application startup.
<font color="#A6E22E">INFO</font>:     Application startup complete.
<font color="#A6E22E">INFO</font>:     Started server process [<font color="#A1EFE4">27367</font>]
<font color="#A6E22E">INFO</font>:     Waiting for application startup.
<font color="#A6E22E">INFO</font>:     Application startup complete.

ここで唯一の新しいオプションは --workers で、Uvicornに4つのワーカー・プロセスを起動するように指示しています。

各プロセスの PID が表示され、親プロセスの 27365 (これは プロセスマネージャ) と、各ワーカー・プロセスの PID が表示されます: 27368273692737027367になります。

デプロイメントのコンセプト

ここでは、アプリケーションの実行を**並列化**し、CPUの**マルチコア**を活用し、より多くのリクエスト**に対応できるようにするために、**Gunicorn(またはUvicorn)を使用して**Uvicornワーカー・プロセス**を管理する方法を見ていきました。

上記のデプロイのコンセプトのリストから、ワーカーを使うことは主に**レプリケーション**の部分と、**再起動**を少し助けてくれます:

  • セキュリティ - HTTPS
  • 起動時の実行
  • 再起動
  • レプリケーション(実行中のプロセス数)
  • メモリー
  • 開始前の事前のステップ

コンテナとDocker

次章のコンテナ内のFastAPI - Dockerでは、その他の**デプロイのコンセプト**を扱うために実施するであろう戦略をいくつか紹介します。

また、**GunicornとUvicornワーカー**を含む**公式Dockerイメージ**と、簡単なケースに役立ついくつかのデフォルト設定も紹介します。

また、(Gunicornを使わずに)Uvicornプロセスを1つだけ実行するために、**ゼロから独自のイメージを**構築する方法も紹介します。これは簡単なプロセスで、おそらく**Kubernetes**のような分散コンテナ管理システムを使うときにやりたいことでしょう。

まとめ

Uvicornワーカーを使ったプロセスマネージャとして**Gunicorn**(またはUvicorn)を使えば、**マルチコアCPU**を活用して**複数のプロセスを並列実行**できます。

これらのツールやアイデアは、**あなた自身のデプロイシステム**をセットアップしながら、他のデプロイコンセプトを自分で行う場合にも使えます。

次の章では、コンテナ(DockerやKubernetesなど)を使った**FastAPI**について学んでいきましょう。これらのツールには、他の**デプロイのコンセプト**も解決する簡単な方法があることがわかるでしょう。✨