Nginx が「軽量で高速」と言われる理由は何か。
なぜ Apache より少ない CPU で大量の接続を捌けるのか。
そして QUIC や io_uring といった最新技術とどう関係しているのか。
この記事では、Nginx の内部構造を イベントループ → epoll → upstream keepalive → proxy_cache → LRU → zero-copy → QUIC → timer wheel の順に体系的に整理します。
単なる設定解説ではなく、
「Nginx がどう動いているのか」
「Linux カーネルとどう連携しているのか」
「QUIC や io_uring とどうつながるのか」
を“設計思想レベル”で理解できる内容です。
目次
1.Nginx の内部構造
2.Nginx のイベントループと epoll
3.upstream keepalive の内部構造
4.proxy_cache のディスク構造と LRU
5.limit_req のアルゴリズム
6.sendfile / splice / io_uring の違い
7.QUIC(HTTP/3)の内部構造
8.Nginx の timer wheel
9.Nginx ソースコードの読み方ガイド
10.io_uring + Nginx の将来像
11.QUIC 実装(quiche)の読みどころ
1. Nginx の内部構造(全体像)
Nginx は イベント駆動・非同期・シングルスレッド(worker) の構造を持つ。
master process
└── worker process (複数)
└── event loop(1 worker = 1 event loop)
- master:設定読み込み、worker 管理
- worker:実際のリクエスト処理
- event loop:epoll/kqueue による非同期 I/O
プロセス構造
graph TD
A[master process] --> B[worker process #1]
A --> C[worker process #2]
A --> D[worker process #3]
B --> E[event loop]
C --> F[event loop]
D --> G[event loop]
2. Nginx のイベントループと epoll
Nginx の高速性の核心は epoll + event loop。
while (true) {
events = epoll_wait();
for (event in events) {
handler(event);
}
}
handler の種類:
- accept handler
- read handler
- write handler
- upstream handler
- timer handler
accept mutex により複数 worker の accept() 競合を防ぐ。
● epoll の役割
- 非同期 I/O
- 大量接続を効率処理
- accept mutex による競合回避
3. upstream keepalive の内部構造
upstream keepalive は worker ローカルの接続プール。
idle connection list
├── fd
├── last_used
├── upstream addr
└── flags
- worker ごとに独立
- shared memory は使わない(FD は共有不可)
- idle が満杯なら古いものから削除
graph LR
A[Idle Connection Pool] --> B[fd]
A --> C[last_used]
A --> D[upstream addr]
A --> E[state: idle/busy]
4. proxy_cache のディスク構造と LRU
Nginx のキャッシュは メタデータは shared memory、実体はディスク。
/var/cache/nginx/
├── a1/
│ └── b2/
│ └── HASHED_FILENAME
メタデータ(shared memory):
- key(ハッシュ)
- expire
- size
- path
- LRU doubly-linked list
LRU の動作:
- ヒット → 先頭へ移動
- 新規 → 先頭へ
- 容量超過 → 末尾から削除
ディスク構造
graph TD
A[/var/cache/nginx/] --> B[a1/]
B --> C[b2/]
C --> D[HASHED_FILE]
メタデータ(shared memory)
graph TD
A[shared memory zone] --> B[key hash]
A --> C[expire]
A --> D[size]
A --> E[disk path]
A --> F[LRU prev/next]
5. limit_req のアルゴリズム(トークンバケット)
Nginx のレート制限は トークンバケット方式。
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
- 1秒ごとにトークン追加
- リクエストでトークン消費
- 無ければ 503
- burst によりスパイク吸収可能
graph TD
A[Bucket] --> B[tokens added per second]
A --> C[request consumes token]
A --> D[no token → 503]
6. sendfile / splice / io_uring の違い
| 術 | 特徴 |
| sendfile | ファイル → カーネル → NIC(zero-copy) |
| splice | FD → pipe → FD(より汎用) |
| io_uring | 完全非同期 I/O、syscall 削減、次世代 I/O |
Nginx は静的ファイル配信に sendfile を採用。
7. QUIC(HTTP/3)の内部構造
QUIC は UDP 上で TCP を再実装したプロトコル。
パケット構造
- Connection ID
- Packet Number
- Encrypted Payload(STREAM, ACK など)
graph TD
A[QUIC Connection] --> B[Stream 1]
A --> C[Stream 2]
A --> D[Stream 3]
特徴
- 再送パケットは 新しい packet number
- ACK は「範囲」で返す(ACK range)
- ストリーム単位で独立したフロー制御
- head-of-line blocking が無い
8. Nginx の timer wheel
大量のタイムアウトを効率管理するための仕組み。
- ソート木(赤黒木) or タイムホイール
- event loop が「期限切れイベント」を処理
- keepalive timeout、request timeout などを管理
graph TD
A[Timer Wheel] --> B[slot0: timeout A]
A --> C[slot1: timeout B]
A --> D[slot2: empty]
A --> E[slot3: timeout C]
9. Nginx ソースコードの読み方ガイド
src/event/
- ngx_event.c:イベントループの中心
- ngx_event_epoll.c:epoll 実装
- ngx_event_timer.c:タイマー管理
src/http/
- ngx_http_request.c:HTTP リクエスト処理
- ngx_http_upstream.c:upstream 処理
- ngx_http_file_cache.c:キャッシュ実装
- ngx_http_limit_req_module.c:レート制限
読む順番(おすすめ)
- ngx_event.c(イベントループ)
- ngx_event_epoll.c(I/O 多重化)
- ngx_http_request.c(HTTP 処理)
- ngx_http_upstream.c(proxy_pass)
- ngx_http_file_cache.c(キャッシュ)
読むべきファイル一覧
src/event/ngx_event.c
src/event/modules/ngx_epoll_module.c
src/http/ngx_http_request.c
src/http/ngx_http_upstream.c
src/http/ngx_http_file_cache.c
src/http/modules/ngx_http_limit_req_module.c
- io_uring + Nginx の将来像
Nginx は現在 epoll ベースだが、
将来的には io_uring による 完全非同期 I/O が可能。
- epoll → io_uring への移行可能性
- 完全非同期化
- sendfile の置き換え候補
置き換えポイント
- accept
- read/write
- sendfile の代替
- timerfd との統合
課題
- Nginx のイベントモデルが epoll 前提
- io_uring は「I/O 完了通知」モデル
- 大規模改修が必要
- QUIC 実装(quiche)の読みどころ
Cloudflare の quiche は QUIC 実装として非常に読みやすい。
読むべきファイル
- src/packet.rs:パケット構造
- src/recovery.rs:loss detection
- src/stream.rs:ストリーム管理
- src/frame.rs:フレーム処理
注目ポイント
ACK range の処理
packet number space
loss detection(RFC9002)
フロー制御
🎉 まとめNginx の高速性は、単なる設定の話ではなく
Linux カーネル・ネットワークプロトコル・非同期 I/O の設計思想が融合した結果です。
- イベント駆動
- epoll
- upstream keepalive
- proxy_cache
- LRU
- zero-copy
- QUIC
- timer wheel
- io_uring
これらを体系的に理解すると、
Nginx の挙動が「ブラックボックス」から「透明な構造物」に変わります。
この記事が、Nginx の内部構造を深く理解するための
永久保存版のリファレンスになれば幸いです。