Gunicorn(Python製WSGIサーバーのデファクト)とGranian(Rust製HTTPスタックを内包した次世代サーバー)を、アーキテクチャ、メモリ効率、並行処理性能、実運用上の堅牢性・リスクの4つの軸で比較します。
GitHub – emmett-framework/granian: A Rust HTTP server for Python applications
A Rust HTTP server for Python applications. Contribute to emmett-framework/granian development by creating an account on…
1. アーキテクチャの根本的な違い
両者の最大の違いは、「HTTP I/O処理とPythonランタイムの境界線をどこに置いているか」 です。
| 項目 | Gunicorn (+ gthread / UvicornWorker) | Granian (Rust / PyO3) |
| I/O・ネットワーク層 | Python標準ライブラリ(socket, select, asyncio) | Rust(Tokio + Hyper) |
| HTTPパース | C拡張(http-parser / httptools)またはPython | Rust(Hyper / httparse) |
| Pythonとの接続 | 同一プロセス内の純粋なPython呼び出し | PyO3(C-API経由)によるネイティブバインディング |
| 対応インターフェース | WSGI標準(ASGIはUvicornWorkerが必要) | WSGI, ASGI, RSGI を単一バイナリでネイティブ対応 |
| HTTPバージョン | HTTP/1.1 (HTTP/2はリバースプロキシ任せ) | HTTP/1.1, HTTP/2 (TLS終端含む) |
- Gunicorn: 伝統的な「Pre-forkモデル」。マスターがソケットを開き、ワーカーが各自で accept・パース・WSGI実行までをすべてPythonプロセス空間内で行います。
- Granian: リクエストの受付、TLSハンドシェイク、HTTP/2多重化、ヘッダー解析などの重いI/O処理をRustのスレッドプール(Tokio)がゼロコピーに近い形で処理し、Pythonのコードを実行する直前になって初めてPyO3経由でPythonのGIL(Global Interpreter Lock)を握って呼び出します。
![[Rust]GranianとGunicornの比較](https://mtoy.work/develop/wp-content/uploads/sites/3/2026/05/Nginx-logo-160x90.png)
[Nginx]Python(Gunicorn+Flask)を実行
NginxとPython(Gunicorn+Flask)を連携させてWebアプリを動作させる方法を解説。Nginxをリバースプロキシとして設定し、WSGIサーバーであるGunicornを介してFlaskを実行する手順がステップバイステップで理解できます。
2. メモリフットプリントとスワップ耐性(2GB VPS視点)
今回のVPS障害のような低メモリ環境において、両者の挙動には明確な差が出ます。
| メモリ消費要因 | Gunicorn | Granian |
| ランタイム自体の基本消費 | ワーカーあたり 約 30MB〜50MB | ワーカーあたり 約 5MB〜15MB |
| 多数のコネクション維持 | 接続数に比例してPythonヒープが増加 | RustのTokioタスクで維持(1接続あたり数KB) |
| スレッド追加コスト | OSネイティブスレッド+Pythonスレッド状態 | Rustの軽量グリーンスレッド(M:Nモデル) |
| メモリの自律返却 | Pythonヒープ断片化でOSにメモリが戻りにくい | ネットワークバッファはRustのメモリアロケータ(jemalloc等)で即座に返却 |
プロ目線の実態
- Rust層の恩恵: コネクションが数千に膨らんだり、巨大なHTTPヘッダーが飛び込んできても、サーバー本体のメモリはほとんど増えません。Gunicornで発生しがちな「通信待ちだけでメモリを食い潰す」現象はほぼ皆無になります。
- 越えられない壁: Django ORMが取得したモデルインスタンス、PandasのDataFrame、Pythonの辞書オブジェクトはすべてPythonのヒープ領域(OS管理外)に作られます。アプリ側で100MBのデータを展開すれば、Granianであっても物理メモリは100MB消費されます。
![[Rust]GranianとGunicornの比較](https://mtoy.work/develop/wp-content/uploads/sites/3/2026/04/apple-logowebp-160x90.png)
[Mac]Ubuntuインストール用USBメモリを作成
Macを使ってUbuntuのインストール用USBメモリを簡単かつ安全に作成する方法を解説。GUIツール「balenaEtcher」を使用した手順や、作成後の警告メッセージへの対処法、作成したUSBからの起動方法まで初心者向けに紹介します。
3. スループットとレイテンシ(並行処理性能)
ベンチマーク(wrk / autocannon等)における典型的な性能差です。
- プレーンなJSON / I/O待ち中心のAPI:
- Granian が Gunicornの 2〜4倍 のRPS(Requests Per Second)を記録します。
- 特にFastAPI(ASGI)やHTTP/2環境では、イベントループをRust側で処理するためCPUのボトルネックがPythonから完全に切り離され、p99レイテンシが大幅に平滑化されます。
- 重いDBクエリや計算処理を伴うDjango (WSGI):
- ボトルネックが「Pythonコードの実行時間(GIL)」や「DBの応答速度」に移るため、実効スループットの差は 10〜30% 程度に縮まります。
4. 運用・保守性の比較(メリットと地雷)
現場で置き換えを検討する際の最大の判断材料となる項目です。
Gunicorn の強みと弱み
- 強み:
- 圧倒的な歴史と実績(トラブル時の知見が世界中に蓄積されている)。
- 設定オプションの豊富さ(
--max-requests,--max-requests-jitter,--preload,--graceful-timeoutなど、プロセスライフサイクル制御が極めて洗練されている)。
- 弱み:
- WSGIとASGIで設定やワーカークラスがバラバラになる。
- HTTPスタック自体が古く、HTTP/2非対応。リバースプロキシ(Nginx)の前段配置が必須。
Granian の強みと弱み
- 強み:
pip install granianだけでCコンパイラ不要で入り、Rustの依存関係はホイールに含まれている。- WSGI(Django)とASGI(FastAPI)を全く同じコマンド体系で統一管理できる。
- リバースプロキシなしでもHTTP/2を直接喋れるため、ローカル開発や内部通信のオーバーヘッドが小さい。
- 弱み(運用上のリスク):
- プロセスの自己再起動制御(
max-requests相当)がGunicornほど細やかでない:
Granianにも--respawn-failed-workersなどの監視はありますが、Gunicornのように「500リクエスト処理したら安全にプロセスを自決させてリークを防ぐ」というPython特有のメモリ断片化対策は、外側(systemdのRuntimeMaxSecなど)に依存する設計思想です。 - PyO3境界での予期せぬパニック:
Pythonの拡張Cモジュール(C-APIを直接叩く特殊なライブラリや非標準なシグナルハンドラ)と組み合わせた際、Rust層で未捕捉の例外が起きた場合のトラブルシューティング難易度が上がります。
- プロセスの自己再起動制御(
5. 比較総括表
| 項目 | Gunicorn | Granian |
| 開発言語 | Python (一部C) | Rust + Python |
| 安定性・運用実績 | ★★★★★ 業界標準・極めて堅牢 | ★★★★☆ 実運用導入が急速に拡大中 |
| スループット / レイテンシ | ★★★☆☆ 標準的 | ★★★★★ 爆速・低遅延 |
| 省メモリ性 (基盤部分) | ★★☆☆☆ 数十MB〜100MB | ★★★★★ 数MB〜十数MB |
| メモリリーク防衛機能 | 優秀 max-requests | △ systemd等の外部制御が必須 |
| Django (WSGI) との相性 | 最高 標準構成 | 良好 WSGIインターフェースで動作 |
| FastAPI (ASGI) との相性 | △ UvicornWorkerが別途必要 | 最高 ネイティブ最適化 |
結論:使い分けるべきか?
もし導入を試すなら、まずは FastAPIで動いているサービスから granian --interface asgi で検証導入し、安定性を確認した上でDjango(WSGI)への水平展開を検討するのが最もリスクの低いアプローチです。
- Djangoメインで、バックグラウンド処理やDBアクセスが重いサービス:
- Gunicornを継続利用(設定最適化)するのが最も安全。
今回実施した--workers 1~2,--max-requests 300, systemdのMemoryMaxを適用したGunicornは、極めて枯れており予測可能性が高いです。無理にGranianに置き換えても、Django ORM側のメモリ消費が主因である場合は劇的な劇薬にはなりません。
- Gunicornを継続利用(設定最適化)するのが最も安全。
- FastAPIや、I/Oバウンド(外部APIの中継・WebSocket・高頻度ポーリング)なサービス:
- Granian への移行を強く推奨。
Uvicorn + Gunicorn の組み合わせに比べ、CPU使用率・メモリ消費ともに大幅に削減され、明らかなパフォーマンス向上が得られます。
- Granian への移行を強く推奨。


コメント