コンテンツにスキップ

Server Workers - Gunicorn と Uvicorn

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

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

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

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

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

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

Info

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

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

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

GunicornWSGI標準のアプリケーションサーバーです。このことは、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について学んでいきましょう。これらのツールには、他のデプロイのコンセプトも解決する簡単な方法があることがわかるでしょう。✨