Flaskアプリを高速化!Gunicornのワーカー数調整でスループットを改善する完全ガイド
生徒
「Flaskで作ったWebサイトにアクセスが集中すると、画面がなかなか表示されなくなってしまいます。サーバーの性能をフルに引き出す方法はありますか?」
先生
「それは『Gunicorn(グニカーン)』のワーカー数を調整することで解決できるかもしれません。ワーカーとは、注文をさばく料理人のような存在のことですよ。」
生徒
「料理人ですか!ワーカーをたくさん増やせば、それだけサイトも速くなるのでしょうか?」
先生
「実は増やせば良いというわけではなく、厨房の広さに合わせた最適な数があるんです。効率的な設定方法を一緒に学んでいきましょう!」
1. Gunicornとワーカーの役割を理解しよう
パソコンを触ったことがない方でもイメージしやすいように、Webサイトの仕組みを「レストラン」に例えて解説します。あなたが作った「Flask(フラスク)」は料理のレシピです。そして、そのレシピを見て実際に調理を行い、お客さんに届けるスタッフが「Gunicorn」というサーバープログラムです。
このGunicornの中で、実際に一つひとつの注文(リクエスト)を処理する担当者のことを「ワーカー」と呼びます。ワーカーが1人しかいないと、同時にお客さんが10人来たときに、10人目は前の9人の料理が終わるまでずっと待たされることになります。これを解消し、同時にこなせる仕事量(スループット)を増やすのが、ワーカー数の調整なのです。
2. スループットとレスポンスタイムの違い
パフォーマンス最適化を考える上で大切な二つの言葉があります。一つは「レスポンスタイム」で、これは料理一皿が完成するまでの時間です。もう一つが「スループット」で、これは「1分間に何皿の料理を出せるか」という合計の処理能力を指します。
ワーカー数を増やす目的は、主にこの「スループット」を改善することにあります。一人ひとりの待ち時間を減らし、全体として多くのアクセスをさばけるようにすることで、サイト全体の快適さが向上します。検索エンジン最適化(SEO)の観点からも、スループットが高く安定したサイトはGoogleから高く評価されやすくなるため、非常に重要な設定項目です。
3. サーバーの核「CPUコア数」を確認する
ワーカー数を決める上で最も重要な指標が、サーバーの「CPU(シーピーユー)コア数」です。CPUはパソコンの頭脳であり、コア数は「頭脳の数」や「調理コンロの数」に例えられます。コンロが2つしかないのに料理人を100人雇っても、お互いが邪魔になって効率が落ちてしまいますよね。
一般的に、Gunicornの最適なワーカー数は「(CPUのコア数 × 2) + 1」と言われています。例えば、コア数が2つのサーバーなら、ワーカー数は5個にするのが標準的です。まずは、自分のサーバーの力を知ることから始めましょう。
4. 基本的なGunicornの起動コマンド
実際にGunicornを起動する際に、どのようにワーカー数を指定するのかコードを見てみましょう。ここでは、もっとも標準的な「同期ワーカー」という仕組みを使った例を紹介します。コマンドプロンプトやターミナルという黒い画面に入力する命令文です。
# gunicorn という道具を使い
# -w 4 でワーカーの数を4人に指定
# app:app でプログラムを読み込んで起動します
gunicorn -w 4 app:app
このように -w という文字の後に数字を入れるだけで、ワーカーの数を自由に変更できます。まずはこの基本の形を覚えて、自分のサーバーに合わせて数字を調整してみるのがスループット改善の第一歩となります。
5. 設定ファイルで管理を楽にする方法
起動するたびに長いコマンドを打つのは大変です。そこで、設定を一つのファイルにまとめて管理する方法がおすすめです。これなら、設定内容を忘れる心配もありませんし、後から修正するのも簡単です。パソコンのメモ帳を作るような感覚で作成できます。
# gunicorn_config.py という名前で保存するファイルの中身
# サーバーが待ち受ける場所(ポート番号)
bind = "0.0.0.0:8000"
# ワーカーの数(料理人の数)
workers = 5
# タイムアウト(何秒反応がなかったらやり直すか)
timeout = 30
このファイルを作っておけば、次回からは gunicorn -c gunicorn_config.py app:app と打つだけで、いつでも決まった設定で爆速なサーバーを起動できるようになります。運用の安定性を高めるためにも、設定ファイルの利用はプロの間でも推奨されているテクニックです。
6. 重い処理には「非同期ワーカー」を使おう
もし、あなたのFlaskアプリが「他のサイトからデータを取ってくる」や「大量の計算をする」といった、時間のかかる作業を含んでいるなら、「非同期ワーカー」という特殊なスタッフを雇うのが効果的です。代表的なのが gevent(ジェベント)という道具です。
# 非同期ワーカー gevent を使う場合の起動コマンド
# 待ち時間が多いアプリでは、驚くほどスループットが向上します
gunicorn -w 4 -k gevent app:app
通常のワーカーは仕事が終わるまでその場を離れませんが、非同期ワーカーは「待ち時間」が発生した瞬間に別の仕事に取り掛かることができます。行列ができる人気店で、注文だけ先に取って効率よく回すようなイメージですね。これにより、限られたサーバー資源を最大限に活用できます。
7. メモリ使用量とのバランスに注意
「ワーカーを増やせば増やすほど速くなる」という誘惑に駆られるかもしれませんが、注意点があります。それは「メモリ」の消費です。ワーカーは一人雇うごとに、サーバーの作業机(メモリ)を一定量占有します。
もしメモリが足りなくなると、サーバー全体が急激に重くなり、最悪の場合はアプリが強制終了してしまいます。ワーカー数を増やした後は、パソコンのタスクマネージャーのようなツールで、メモリに余裕があるかを確認することが大切です。無理のない範囲で、最適な人数を見極めるのがパフォーマンス最適化の醍醐味です。
8. 実際にスループットを計測してみる
設定を変えたら、本当に効果があったのか確かめてみましょう。これには「負荷テスト」という作業を行います。一度にたくさんのアクセスを疑似的に発生させて、どれくらいの速度でさばけるかをテストします。
(実行結果のイメージ)
Requests per second: 150.23 [#/sec] # 1秒間に150件さばけている!
Time per request: 6.65 [ms] # 1件あたりの時間は0.006秒!
このように数字で結果を見ると、ワーカー数を1つ変えるだけでどれだけ性能が改善したかが一目瞭然です。勘に頼らず、データに基づいて設定を追い込んでいくのが、プロのエンジニアへの近道です。初心者の方も、まずは小さな数字の変化を楽しむことから始めてみてください。
9. 定期的な再起動で安定性を保つ
ワーカーを長時間働かせ続けると、稀にメモリの使い方が乱れてくることがあります(これをメモリリークと呼びます)。これを防ぐために、一定の注文数をこなしたら自動でワーカーを新しいスタッフに入れ替える設定があります。
# 1000回のリクエストを処理したら、ワーカーを新しく作り直す設定
gunicorn --max-requests 1000 --max-requests-jitter 50 app:app
max-requests-jitter は、複数のワーカーが同時に一斉に交代してサイトが一時停止するのを防ぐための「ゆらぎ」の設定です。こうした細かな気配り設定を行うことで、24時間365日、止まることのない安定したWebサービスを提供できるようになります。
10. 最適化への道は一歩ずつ
FlaskとGunicornを組み合わせたパフォーマンス最適化は、奥が深い世界です。しかし、今日学んだ「CPUコア数に合わせたワーカー数の調整」と「非同期ワーカーの活用」の二つを押さえるだけで、あなたのアプリの性能は劇的に向上します。
プログラミングは魔法ではありません。一つひとつの設定がなぜ必要なのか、料理人の例えのようにイメージしながら進めていけば、必ず理解できるようになります。まずは自分のサーバーでワーカー数を「3」や「5」に変更して、サイトの動きがどう変わるか観察してみてください。その積み重ねが、最高のユーザー体験を生む爆速サイトへと繋がっていくはずです!