Gunicornってなんだろう?WSGIってなんだろう?
以下はGunicornについてChatGPTに聞きまくったのと、以下のサイトで勉強して、まとめた内容です。
https://wsgi.readthedocs.io/en/latest/what.html
Djangoとかの書籍買っても(初学者向け)この辺の解説をしてくれる本てなくて「とりあえず、そんなものがあるんだなってことで次に読み進めてください」って感じで省略されちゃう(はぐらかされちゃう)
でも気になるから調べてみた。
イントロダクション
GunicornやWSGIという言葉を初めて聞いた方も多いと思います。特に、DjangoやFlaskなどのPythonを使ったWebアプリケーションを作成し始めたばかりの方にとっては、「これらが何のために必要なのか?」と疑問に思うかもしれません。
まずはWSGIから
PythonのWebアプリケーションとWebサーバーを繋ぐための「標準的な規格(プロトコル)」です。要するに、WSGIはPythonのアプリとWebサーバーが「会話」するための共通の言語を提供してくれる役割を担っています。
Webサーバー(NginxやApacheなど)は、HTTPリクエストを受け取る仕事をしていますが、直接Pythonアプリケーションを実行する能力はありません。ここでWSGIが重要になります。WSGIがあることで、Webサーバーが受け取ったHTTPリクエストをPythonアプリケーションが理解できる形に変換し、逆にPythonアプリが返すレスポンスをWebサーバーが理解できる形に変換してくれるのです。
これにより、Pythonで作ったWebアプリケーション(例:DjangoやFlask)をWeb上で動かすことができるようになります。
要は通訳です。
Webサーバー(Nginx)は「HTTP」という言語を話し、Pythonアプリケーションは「Python」という言語を話します。それぞれが別々の言語を話しているので、直接やり取りをすることはできません。しかし、WSGIはその2つの言語を理解しているので、両者がスムーズにコミュニケーションできるようにしてくれる
ちなみに
サーバーでも、Pythonモジュールでも、フレームワークでも、APIでも、その他のソフトウェアでもありません。サーバーとアプリケーションが通信するためのインターフェース仕様にすぎません。
クライアントからのリクエストを受信し、それをアプリケーションに渡し、アプリケーションから返された応答をクライアントに送信するだけです。それ以外は何も行いません
Gunicornとは何か?
Gunicornの意味
Gunicorn(Green Unicornの略)は、Pythonで書かれたWSGIサーバーです。WSGIがPythonアプリケーションとWebサーバーの間での「通訳」の役割を果たすことはわかりましたが、実際にその通訳を動かすためには「WSGIサーバー」が必要です。Gunicornは、このWSGIサーバーの1つです。
WSGIサーバーは、Pythonアプリケーションを実行し、Webサーバー(例えばNginxなど)からのリクエストを受け取って、アプリケーションを動かし、その結果をWebサーバーに返します。
Gunicornは特にDjangoやFlaskなどのWebアプリケーションフレームワークと一緒に使われることが多く、PythonのWebアプリケーションを本番環境で動かすために一般的に使用されます。
Gunicornの役割
Gunicornは、以下の役割を果たします。
リクエストの処理
Gunicornは、Webサーバー(例:Nginx)から送られてきたリクエストを受け取ります。そして、そのリクエストをPythonアプリケーション(DjangoやFlaskなど)が理解できる形で処理します。並行処理
Gunicornは、1つのリクエストだけを処理するのではなく、同時に複数のリクエストを処理することができます。これを実現するために、Gunicornは「ワーカー」という仕組みを使います。スケーラビリティ
アクセスが増えるにつれて、Gunicornは追加のワーカーを生成することで、効率よくリクエストを処理できます。この仕組みのおかげで、負荷が増えたときでもスムーズに処理が行われます。
GunicornとWebサーバ(例としてNginx)との連携
Gunicornは通常、NginxのようなWebサーバーと一緒に使われます。今回はとりあえずNginxを例に解説します。
Nginxは主に以下の役割を担います。
静的ファイル(画像やCSS、JavaScriptなど)の提供
負荷分散やプロキシの役割
対してGunicornは動的なリクエスト(例えば、データベースとやり取りして生成されるコンテンツ)を処理します。一方で、Nginxはその処理結果をクライアントに返す役割を担います。
一旦ここまでをまとめる
WSGIとWebサーバの違い:
Webサーバ(例:Nginx、Apache): クライアントからのHTTPリクエストを受け取り、静的ファイルを提供したり、動的コンテンツの要求を適切なバックエンドに転送したりします。
WSGIサーバ(例:Gunicorn): Pythonアプリケーションを実行し、WSGI仕様に従ってWebサーバとアプリケーション間の通信を処理します。
例としてNginxとGunicornの関係:
Nginx: フロントのWebサーバとして機能し、静的ファイルの提供や負荷分散を担当します。
Gunicorn: WSGIサーバとして、NginxとPythonアプリケーションの間に位置し、アプリケーションコードを実行します。
ここまでを踏まえてシステム設計をしてみて理解する
Webサーバー(例:Nginx)をフロントに配置
通常、NginxのようなWebサーバーがフロントエンドとして配置されます。Nginxはクライアントからのリクエストを受け取り、それが静的コンテンツ(画像、CSS、JavaScriptなど)の場合は、そのままクライアントにレスポンスを返します。動的コンテンツはGunicornにプロキシする
クライアントがリクエストしたページが動的なものである場合(例えば、データベースから情報を取得してページを生成するなど)、NginxはそのリクエストをGunicornにプロキシ(中継)します。GunicornはPythonアプリケーションを使ってリクエストを処理し、その結果をNginxに返します。Nginxはその結果をクライアントに返す役割を担います。
この設計の概要
効率的な静的コンテンツの提供
Nginxは静的コンテンツ(HTML、CSS、画像など)を非常に効率よく処理できます。Gunicornに動的コンテンツのみを処理させることで、システム全体の効率が向上します。Nginxはリソースをほとんど消費せず、クライアントに高速に静的コンテンツを配信することができます。動的コンテンツのスケーラビリティ
Gunicornは複数の「ワーカー」プロセスを使って動的リクエストを処理します。これにより、同時に多数のリクエストを処理することができ、大量アクセス時でもシステムが安定して動作するようになります。Gunicornを単独で使うのではなく、Nginxと組み合わせることで、処理の分担がはっきりし、全体のパフォーマンスが向上します。
NginxとGunicornのインストール場所について
システム設計の際、NginxとGunicornをどこにインストールするべきかについては、主に2つの選択肢があります。それぞれのメリットとケースごとの適用シナリオについても解説します。
1. NginxとGunicornを同じ物理マシンにインストールする
一般的には、NginxとGunicornは同じマシンにインストールされることが多いです。この構成は、シンプルで管理がしやすく、中規模程度のトラフィックを処理するアプリケーションには十分対応できます。
メリット
設定が簡単で、システム全体の管理がしやすい。
物理マシンを1つだけ用意すれば良いので、コストが抑えられる。
NginxとGunicorn間の通信はローカルで行われるため、ネットワーク遅延がほぼなく、効率的に動作する。
適したケース
小〜中規模のアプリケーション。
単一のVM(仮想マシン)でアプリケーションをデプロイしたい場合。
コストを抑えつつ、シンプルなシステム設計が求められる場合。
2. NginxとGunicornを別々のマシンにインストールする
大規模なトラフィックを処理する必要がある場合や、負荷を分散したい場合には、NginxとGunicornを異なる物理マシンにインストールするという選択肢もあります。
GunicornをPythonアプリケーションが動くマシンにインストールする GunicornはPythonアプリケーションを実行するWSGIサーバーです。そのため、Pythonアプリが動作するマシンにGunicornをインストールする必要があります。この場合、Nginxはフロントエンドに配置され、リクエストをGunicornの動いている別のサーバー(マシン)にプロキシします。
メリット
スケーラビリティが高い。NginxとGunicornをそれぞれ異なるマシンで運用することで、負荷分散が可能。
可用性が高まる。1つのマシンに障害が発生しても、他のマシンが動作し続ける。
大規模なトラフィックにも対応できる。複数のPythonアプリケーションマシンにGunicornを配置してリクエストを分散することができる。
適したケース
大規模なトラフィックが予想されるアプリケーション。
サービスの可用性を高めたい場合(例えば、複数の地域にサーバーを分散する場合)。
負荷を分散し、NginxとGunicornに別々の役割を明確にしたい場合。
番外編
ワーカー
ワーカー(Worker):
ワーカーは独立したプロセスです。
各ワーカーは、アプリケーション(この場合はDjango)の完全なコピーを実行します。
ワーカーは並行して動作し、それぞれが独立してリクエストを処理できます。
プロセス vs スレッド:
プロセス: オペレーティングシステムによって管理される、独立したプログラム実行の単位です。各プロセスは独自のメモリ空間を持ちます。
スレッド: 1つのプロセス内で実行される軽量な実行単位です。同じプロセス内のスレッドはメモリを共有します。
Gunicornのワーカーモデル:
Gunicornは通常、マルチプロセスモデルを使用します。
各ワーカーは別々のプロセスとして実行されます。
これにより、1つのワーカーが問題を抱えても、他のワーカーには影響しません。
プロセスベース vs スレッドベース:
Gunicornのデフォルトは「同期ワーカー」で、これはプロセスベースです。
一方、一部のアプリケーションサーバーはスレッドベースのモデルを使用します。
なぜプロセスベースなのか:
Python の GIL(Global Interpreter Lock)の制約を回避できます。
プロセス間のメモリ分離により、安定性が向上します。
各ワーカーが独立しているため、1つのワーカーの問題が他に波及しにくいです。
デメリット:
プロセスはスレッドよりもメモリを多く使用します。
プロセス間の切り替えは、スレッド間の切り替えよりもコストがかかります。
簡単な例え: ワーカーは、レストランの厨房で働くコックさんのようなものです。各コックさん(ワーカー)は独立して注文(リクエスト)を処理できます。コックさんを増やせば(ワーカー数を増やせば)、同時に処理できる注文の数が増えます。
Python以外の言語でのWSGI的なもの
WSGIはPythonのために作られた特定の規格であり、他のプログラミング言語にはそれぞれに応じた似たようなインターフェースやゲートウェイの仕組みが存在します。つまり、他の言語にはWSGIそのものは存在しませんが、同様の役割を果たす技術やインターフェースが各言語で採用されています。以下は、各言語でWSGIに相当する技術です。
他の言語におけるWSGIに相当するインターフェース
Java: Servlet API
Javaでは、Webアプリケーションを構築するために「Servlet API」が標準として使われています。Servletは、JavaベースのWebアプリケーションとWebサーバー(TomcatやJettyなど)とのやり取りを標準化した仕組みで、WSGIと似た役割を果たします。
Servlet APIの役割: JavaアプリケーションがHTTPリクエストを処理する際、Servlet APIがそのインターフェースとなります。
Ruby: Rack
RubyのWebアプリケーションでは、「Rack」というインターフェースが広く使われています。Rackは、RubyのWebサーバー(PumaやUnicornなど)とRubyアプリケーションを繋ぐための標準化されたインターフェースです。
Rackの役割: HTTPリクエストを受け取り、それをRubyアプリケーションに渡し、レスポンスを生成して返すという点で、WSGIに非常に似ています。
PHP: PHP-FPM(FastCGI Process Manager)
PHPはもともとWeb向けに作られた言語であり、WSGIのようなゲートウェイインターフェースは必要ありませんが、PHP-FPM(FastCGI Process Manager)がWebサーバーとのやり取りを最適化するために使われています。これは、PHPアプリケーションが効率的に動作するように管理します。
PHP-FPMの役割: NginxやApacheのようなWebサーバーとPHPのアプリケーションを効率的に繋げる仕組みとして使われます。
Node.js: Connect/Express
Node.jsでは、「Connect」や「Express」のようなミドルウェアフレームワークが使用されています。これらはNode.jsのWebサーバー(HTTPサーバー)とNode.jsアプリケーションをつなぐ役割を持っています。
Express/Connectの役割: これらのフレームワークは、Node.jsアプリケーションがリクエストを処理するための標準的なインターフェースを提供します。WSGIに似て、リクエストを処理し、レスポンスを返すフローをシンプルにします。
Go: net/httpパッケージ
Go言語には「net/http」という標準ライブラリがあり、これを使ってHTTPサーバーを構築し、リクエストとレスポンスの処理を行います。Goの設計思想として、外部のWebサーバーに依存することなく、自前でHTTPサーバーを持つことができるため、WSGIのようなインターフェースは不要です。
net/httpパッケージの役割: Goアプリケーション内で直接リクエストを処理し、レスポンスを返すことができます。
C# (.NET): OWIN (Open Web Interface for .NET)
C#やASP.NETには「OWIN(Open Web Interface for .NET)」というインターフェースがあります。OWINは、.NETアプリケーションとWebサーバー(IISなど)を繋ぐための標準化されたインターフェースです。
OWINの役割: OWINは、WebサーバーからHTTPリクエストを受け取り、それを.NETのアプリケーションに渡すための仕組みで、WSGIと同様の目的を果たします。
この記事が気に入ったらサポートをしてみませんか?