0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【初心者】Gunicorn を使ってみる

Posted at

1. はじめに

  • 業務で「システム内のGunicornに課題がある」という相談があったが、自分としては「そもそもGunicornって何??」という状態だったため、そもそも何なのか、どのように使うものなのかを簡単に確認する。

2. Gunicornとは(自分の理解)

  • Gunicornとは何か?
    • PythonでWebアプリを開発する際のフレームワークとしてDjangoやFlaskがあるが、Gunicornはその前段に配置して、WSGIサーバ(WebアクセスをPythonアプリにつなぐ役割)として動作するもの。
  • FlaskだけでもWebサーバが作れるがそれではダメなのか?
    • Flaskにも開発用サーバ機能がついているが、シングルスレッドであり開発環境向け。Gunicornは複数ワーカーで並列処理ができるなど本番環境向けの対応が可能。
  • 本番環境ではどのような構成になるのか?
    • Nginx(静的資材処理など) - Gunicorn(WSGIサーバ) - Flask(Pythonアプリ) のような構成になる。

3. やったこと

  • EC2インスタンス(Amazon Linux 2023)に、GunicornとFlaskをインストールする。
  • 簡単な初期設定を行い、httpリクエストがGunicornとFlaskでどのように処理されるのかを確認する。

4. 構成図

image.png

5. 手順

5.1 GunicornとFlaskのインストール

  • GunicornとFlaskをインストールする。
[ec2-user@ip-10-0-0-220 ~]$ sudo dnf install -y python3-pip
[ec2-user@ip-10-0-0-220 ~]$ python3 -m venv venv
[ec2-user@ip-10-0-0-220 ~]$ source venv/bin/activate
(venv) [ec2-user@ip-10-0-0-220 ~]$ 
(venv) [ec2-user@ip-10-0-0-220 ~]$ pip install flask==3.0.0
(venv) [ec2-user@ip-10-0-0-220 ~]$ pip install gunicorn==21.2.0

5.2 Gunicornの初期設定

  • Gunicornの設定ファイルを作成する。
gunicorn_config.py
"""
Gunicorn configuration file
"""
import multiprocessing

# Server socket
bind = "0.0.0.0:8000"
backlog = 2048

# Worker processes
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "sync"
worker_connections = 1000
timeout = 30
keepalive = 2

# Logging
accesslog = "-"  # 標準出力にアクセスログを出力
errorlog = "-"   # 標準エラー出力にエラーログを出力
loglevel = "info"
access_log_format = '%(t)s [Worker:%(p)s] %(h)s "%(r)s" %(s)s %(b)s %(M)sms'
  • CPU数x2個のワーカーが推奨?とのことで、今回のEC2インスタンスは2CPUのためワーカー数5個となる。
  • アクセスログは時刻、処理を担当したワーカー、クライアントIP、HTTPメソッド/パス、ステータスコード、レスポンスサイズ、処理時間を取得する。

5.3 Flaskのサンプルアプリ

  • Flaskのサンプルアプリを作製する。(パスなしでアクセスされた場合、GunicornワーカーのプロセスIDをJSONで返す)
app.py
"""
Simple Flask application for Gunicorn demo
"""
from flask import Flask, jsonify
import os

app = Flask(__name__)

@app.route('/')
def index():
    return jsonify({
        'message': 'Hello from Gunicorn!',
        'status': 'running',
        'worker_id': os.getpid()
    })

@app.route('/health')
def health():
    return jsonify({'status': 'healthy'}), 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

5.4 動作確認

Gunicornの起動

  • Gunicornを設定ファイル、およびFlaskアプリのファイルを指定して起動する。
  • 設定どおり、ワーカーが5つ起動される。
(venv) [ec2-user@ip-10-0-0-220 ~]$ gunicorn -c gunicorn_config.py --access-logfile - app:app
[2025-11-10 06:36:23 +0000] [3784] [INFO] Starting gunicorn 21.2.0
[2025-11-10 06:36:23 +0000] [3784] [INFO] Listening at: http://0.0.0.0:8000 (3784)
[2025-11-10 06:36:23 +0000] [3784] [INFO] Using worker: sync
[2025-11-10 06:36:23 +0000] [3785] [INFO] Booting worker with pid: 3785
[2025-11-10 06:36:23 +0000] [3786] [INFO] Booting worker with pid: 3786
[2025-11-10 06:36:23 +0000] [3787] [INFO] Booting worker with pid: 3787
[2025-11-10 06:36:24 +0000] [3788] [INFO] Booting worker with pid: 3788
[2025-11-10 06:36:24 +0000] [3789] [INFO] Booting worker with pid: 3789

curlアクセスの処理

  • インターネット上のクライアントからcurlアクセスする。
  • 何回かアクセスすると、複数のワーカーで処理されていることが分かる。
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3787}
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3785}
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3785}
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3785}
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3786}

アクセスログ

  • 今回はアクセスログを標準出力しており、以下のように出力される。
[10/Nov/2025:06:36:58 +0000] [Worker:<3787>] x.x.x.x "GET / HTTP/1.1" 200 71 2ms
[10/Nov/2025:06:36:59 +0000] [Worker:<3785>] x.x.x.x "GET / HTTP/1.1" 200 71 2ms
[10/Nov/2025:06:37:00 +0000] [Worker:<3785>] x.x.x.x "GET / HTTP/1.1" 200 71 0ms
[10/Nov/2025:06:37:01 +0000] [Worker:<3785>] x.x.x.x "GET / HTTP/1.1" 200 71 0ms
[10/Nov/2025:06:37:02 +0000] [Worker:<3786>] x.x.x.x "GET / HTTP/1.1" 200 71 2ms
[10/Nov/2025:06:37:03 +0000] [Worker:<3786>] x.x.x.x "GET / HTTP/1.1" 200 71 0ms

プロセス障害対応

  • 今回はワーカー数を5個に設定している。
  • ワーカーがプロセスID 4669~4673 で動作している状態で、4671をkillしてもすぐに別のワーカー(5538)が自動的に起動された。
[ec2-user@ip-10-0-0-220 ~]$ ps aux | grep gunicorn
ec2-user    3784  0.0  2.4 245352 22248 ?        S    06:36   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4669  0.0  2.8 254012 26528 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4670  0.0  2.8 254016 26532 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4671  0.0  2.8 254016 26532 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4672  0.0  2.8 254016 26464 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4673  0.0  2.8 254016 26504 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    5537  0.0  0.2 222328  2108 pts/2    S+   06:59   0:00 grep --color=auto gunicorn
[ec2-user@ip-10-0-0-220 ~]$ kill 4671
[ec2-user@ip-10-0-0-220 ~]$ ps aux | grep gunicorn
ec2-user    3784  0.0  2.4 245352 22248 ?        S    06:36   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4669  0.0  2.8 254012 26528 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4670  0.0  2.8 254016 26532 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4672  0.0  2.8 254016 26464 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    4673  0.0  2.8 254016 26504 ?        S    06:54   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    5538  2.6  2.8 254016 26528 ?        S    06:59   0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user    5593  0.0  0.2 222328  2116 pts/2    S+   06:59   0:00 grep --color=auto gunicorn

6. 所感

  • 「Gunicornって何?」という状態からは脱出できたが、実際の環境でどのように設定すべきかなど学習していきたい。
  • 今回もAWS社のコーディングツール「Kiro」のVibeモードを使って、「Gunicornのデモ環境を作って」「ログが出ないんだけど」「Flaskだけの場合と比較してどのようなメリットがあるの?」などのやりとりをして助けてもらった。Vibeモードでちょっとした(理解できる範囲の)コードを作ってもらう分には、便利に使いこなせている気がする。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?