Nginx が「軽量で高速」と言われる理由は何か。
なぜ Apache より少ない CPU で大量の接続を捌けるのか。
そして QUIC や io_uring といった最新技術とどう関係しているのか。
この記事では、Nginx の内部構造を アーキテクチャ → I/O → HTTP → upstream → キャッシュ → QUIC → 未来 の順に体系的に整理します。
単なる設定解説ではなく、
「Nginx がどう動いているのか」
「Linux カーネルとどう連携しているのか」
「QUIC や io_uring とどうつながるのか」
を“技術書レベル”で理解できる内容です。
Nginx の内部を深く理解したいエンジニア、
パフォーマンスチューニングをしたい人、
Linux の I/O モデルを体系化したい人に向けた、
永久保存版のまとめ記事です。
目次
- 第1章:Nginxのアーキテクチャを理解する
- 第2章:Nginxの設定読み込みとserverブロックの選択
- 第3章:server_nameのマッチングとlocationの決定
- 第4章:Nginxの内部処理フェーズ(phase handler)
- 第5章:イベントループとepoll/kqueueの内部
- 第6章:upstreamの内部構造とロードバランシング
- 第7章:proxy_cacheの内部構造とLRU
- 第8章:レート制限(limit_req)の内部
- 第9章:zero-copy I/Oの進化(sendfile→splice→io_uring)
- 第10章:HTTP/2とQUIC(HTTP/3)の内部構造
- 第11章:Nginxのtimer wheel
- 第12章:Nginxソースコードの読み方ガイド
- 第13章:Nginxの未来(io_uring/QUIC)
- 第14章まとめNginxの内部構造を理解するということ
第1章nginx-の-アーキテクチャを理解する
Nginx を深く理解するためには、まずその「思想」を理解する必要があります。
Nginx は単なる Web サーバーではなく、OS の I/O モデル・ネットワークプロトコル・プロセス設計を徹底的に最適化した「イベント駆動型アプリケーションフレームワーク」です。
この章では、Nginx の内部構造を支える 設計思想・プロセスモデル・イベント駆動アーキテクチャ を体系的に解説します。
1.1 Nginx の設計思想
Nginx の設計思想は、次の3つに集約できます。
🔥 1. 非同期・イベント駆動モデル(Event-driven Architecture)
Nginx の最大の特徴は、1つの worker が大量の接続を同時に処理できることです。
これは「イベント駆動モデル」によって実現されています。
● 従来の Web サーバー(Apache MPM)の問題点
- 1接続 = 1スレッド(または1プロセス)
- 接続数が増えるとスレッド数が増え、コンテキストスイッチが増大
- メモリ消費も線形に増える
● Nginx のアプローチ
- 1 worker = 1スレッド
- epoll/kqueue による 非同期 I/O
- イベントが発生したときだけ処理する
- 待ち時間(I/O待ち)で CPU を浪費しない
「スレッドを増やすのではなく、イベントを効率的に処理する」
これが Nginx の高速性の根本です。
🔥 2. 少ない worker で最大のスループット
Nginx は worker を CPU コア数に合わせて起動します。
worker_processes auto;
- 各 worker は 1 CPU コアをフルに使う
- worker 同士は競合しないように設計されている
- マルチスレッドではなく「マルチプロセス」
なぜ worker はスレッドではなくプロセスなのか?
- プロセスはメモリ空間が独立 → 安定性が高い
- 1 worker がクラッシュしても他の worker は生きている
- セキュリティ的にも強い
Nginx は「安定性」を最優先にした設計
🔥 3. OS の I/O モデルを最大限活用する
Nginx は Linux の以下の機能をフル活用します。
- epoll(I/O 多重化)
- sendfile(zero-copy)
- TCP keepalive
- TCP Fast Open
- カーネルバッファの効率的利用
つまり Nginx は OS の性能を引き出すための“薄いレイヤー” として設計されています。
1.2 master / worker モデル
Nginx のプロセス構造は非常にシンプルです。
📌 図:Nginx プロセス構造
master process
├── worker process #1
│ └── event loop (epoll)
├── worker process #2
│ └── event loop (epoll)
└── worker process #3
└── event loop (epoll)
🔧 master process の役割
master は「管理者」であり、実際のリクエスト処理は行いません。
master の仕事
設定ファイルの読み込み・検証
worker の生成・終了
graceful reload(無停止リロード)
シグナル処理(HUP, TERM, QUIT)
master がリクエストを処理しない理由
master が落ちると全体が止まるため
安定性を最優先するため
🔧 worker process の役割
worker は「実働部隊」です。
worker の仕事
- accept() で接続を受ける
- epoll_wait() でイベントを待つ
- HTTP リクエストを処理する
- upstream(バックエンド)と通信する
- 静的ファイルを返す
worker の特徴
- 1 worker = 1 CPU コアをフル活用
- マルチスレッドではなく シングルスレッド
- イベントループで大量の接続を処理
🔧 worker と master の関係
master は worker を管理するだけで、
worker は完全に独立して動作します。
重要なポイント
- worker 同士はメモリを共有しない
- 共有が必要な場合は shared memory zone を使う
- worker が落ちても master が再起動してくれる
Nginx の安定性は、この「プロセス分離」によって支えられている
1.3 event loop(イベントループ)の基本構造
worker は「イベントループ」を回し続けます。
while (true) {
events = epoll_wait();
for (event in events) {
handler(event);
}
}
この構造のメリット
- I/O 待ちで CPU を浪費しない
- 同時接続数が増えてもスレッドが増えない
- メモリ消費が一定
- 高負荷でも安定
1.4 Nginx が Apache より高速な理由
| 項目 | Apache | Nginx |
| モデル | スレッド/プロセス | イベント駆動 |
| 同時接続 | スレッド数に依存 | ほぼ無制限 |
| メモリ消費 | 接続数に比例 | 一定 |
| I/O | ブロッキング | 非同期 |
| 静的ファイル | 普通 | sendfile で超高速 |
Nginx は「スレッドを増やす」のではなく「イベントを効率的に処理する」ことで高速化している。
第1章まとめ
- Nginx の本質は イベント駆動・非同期 I/O
- master/worker モデルで安定性と性能を両立
- worker は 1 CPU コアを最大活用するシングルスレッド
- epoll によって大量の接続を効率的に処理
- sendfile など OS の機能を最大限活用
- Apache とは思想が根本的に違う
第2章nginxの設定読み込みとserverブロックの選択
Nginx の設定は「どのファイルがいつ読み込まれるか」を理解すると一気に整理される。
2.1 include の優先順位
Nginx は設定ファイルを 上から順番に読み込み、後勝ち で評価する。
● Debian 系の読み込み順
- /etc/nginx/nginx.conf
- include /etc/nginx/conf.d/*.conf
- include /etc/nginx/sites-enabled/*
● ASCII ソート順
00-aaa.conf → 10-bbb.conf → 99-zzz.conf
● 結論
sites-enabled が最も強い(最終的に読み込まれる)
2.2 server ブロックのマージルール
Nginx の設定は「内側が外側を上書きする」
http {
server {
location / {
}
}
}
優先順位は:
- location
- server
- http
● SSL 設定は server 単位で完結
ssl_certificate は server ブロック内の設定が絶対優先。
設定読み込み → server 選択のフロー
/etc/nginx/nginx.conf
└── include /etc/nginx/conf.d/*.conf
└── include /etc/nginx/sites-enabled/*
└── server blocks (default_server / SSL / location)
2.3 default_server の仕組み
複数のserverブロックが同じポートをlistenしている場合、どれを使うかを決める仕組みが必要。
それがdefault_server
● default_server が選ばれる条件
- Host ヘッダが無い
- Host がどの server_name にも一致しない
- HTTPS の SNI が無い
● 結論
default_server は「最後の受け皿」
第3章server_name のマッチングとlocationの決定
Nginxの仮想ホスト選択は、server_name → location の順で決まる。
3.1 server_name の優先順位
Nginx は server_name を次の順で評価する
- 完全一致(exact)
- ワイルドカード(前方一致)
- ワイルドカード(後方一致)
- 正規表現(regex)
- default_server
3.2 server_name_hash の内部構造
大量のserver_nameを高速に検索するため、Nginxはハッシュテーブル を使う
- 起動時に server_name をハッシュ化
- Host ヘッダをハッシュ化
- O(1) で検索
● 調整パラメータ
server_names_hash_bucket_size
server_names_hash_max_size
3.3 location マッチングの優先順位
location は次の順で評価される。
- exact (=)
- prefix(最長一致)
- regex(最終勝利)
● 例
location = /about
location /about
location /about/team
location ~ ^/about/[0-9]+$
/about/123 → regex が勝つ
server_name → location 決定フロー
Host ヘッダ
├── 完全一致 (exact)
├── ワイルドカード一致 (prefix/suffix)
├── 正規表現一致 (regex)
└── default_server
location マッチング
├── exact (= /about)
├── prefix (/about/)
└── regex (~ ^/about/[0-9]+$)
第3章まとめ
- server_name → location の順で決まる
- server_name はハッシュで高速検索
- location は exact → prefix → regex
- default_server は最後の受け皿
第4章nginxの内部処理フェーズ(phase handler)
4.1 フェーズ一覧
post-read
server rewrite
find config
location rewrite
access
try_files
content
log
4.2 rewrite と return の優先順位
return は即時終了
rewrite は URL 書き換えのみ
4.3 try_files の評価順
静的ファイル → ディレクトリ → fallback
rewrite より後、content handler より前
📌 図:Nginx リクエスト処理フェーズ
第5章イベントループと epoll/kqueue の内部
5.1 epoll の基本
epoll_ctl
epoll_wait
readiness model
5.2 Nginx の event loop
handler の種類
multi-event
accept mutex
5.3 kqueue / event ports との違い
📌 図:epoll イベントループ
第6章upstreamの内部構造とロードバランシング
6.1 proxy_pass の内部処理
upstream 選択
非同期接続
ストリーミング転送
keepalive 再利用
6.2 upstream keepalive の内部構造
worker ローカルの接続プール
idle / busy / expired
FD は worker 間で共有不可
6.3 ロードバランシングアルゴリズム
round robin
least_conn
ip_hash
hash(consistent)
📌 図:upstream keepalive プール構造
第7章proxy_cacheの内部構造とLRU
7.1 ディスク構造
ハッシュベースの階層
ext4/XFS の最適化
7.2 shared memory のメタデータ
key
expire
size
disk path
LRU リンク
7.3 LRU の実装
近似 LRU
末尾削除
ディスク削除
📌 図:proxy_cache(メモリ+ディスク)
第8章レート制限(limit_req)の内部
8.1 トークンバケット方式
tokens/sec
burst
503 の条件
8.2 shared memory zone の役割
ハッシュテーブル
排他制御(spinlock)
📌 図:トークンバケット
第9章zero-copy I/O の進化(sendfile → splice → io_uring)
9.1 sendfile
ファイル → カーネル → NIC
静的ファイル配信に最適
9.2 splice
pipe 経由の zero-copy
汎用性が高い
9.3 io_uring
SQ/CQ リング
完全非同期
syscall 削減
sendfile の置き換え候補
📌 図:sendfile / splice / io_uring 比較
第10章HTTP/2 と QUIC(HTTP/3)の内部構造
10.1 HTTP/2 のストリーム多重化
フレーム
ストリーム ID
優先度制御
10.2 QUIC のパケット構造
Connection ID
Packet Number
暗号化された payload
10.3 loss detection(RFC9002)
ACK range
packet number space
タイムベース
パケットベース
10.4 フロー制御
ストリーム単位
接続全体
📌 図:QUIC ストリーム構造
第11章nginx の timer wheel
11.1 タイマー管理の課題
keepalive timeout
request timeout
大量のタイマー
11.2 timer wheel の構造
スロット
リスト
O(1) 近い性能
📌 図:timer wheel
第12章nginx ソースコードの読み方ガイド
12.1 event 系
ngx_event.c
ngx_event_epoll.c
ngx_event_timer.c
12.2 http 系
ngx_http_request.c
ngx_http_upstream.c
ngx_http_file_cache.c
ngx_http_limit_req_module.c
12.3 読む順番のおすすめ
第13章nginxの未来io_uring/QUIC
13.1 epoll から io_uring への移行可能性
13.2 QUIC ネイティブサポートの課題
13.3 Nginx Plus と OSS の違い
🏁 第14章:まとめ(永久保存版)
Nginx の高速性の正体
Linux カーネルとの連携
QUIC と io_uring の未来
全体を貫く「イベント駆動」の思想
第14章まとめNginxの内部構造を理解するということ
Nginx の内部構造を体系的に理解すると、
設定ファイルの意味が「暗記」から「理解」に変わります。
- なぜイベント駆動が高速なのか
- なぜ upstream がブロックしないのか
- なぜキャッシュが高速なのか
- なぜ QUIC が HTTP/2 を超えるのか
- なぜ io_uring が次世代 I/O と呼ばれるのか
これらはすべて、
Nginx が Linux カーネルの設計思想と深く結びついているからです。
Nginx は単なる Web サーバーではなく、
「OS とネットワークの設計美をそのまま体現したソフトウェア」です。
この記事が、
Nginx の内部構造を深く理解するための
永久保存版のリファレンスになれば幸いです。
もしこの記事が役に立ったら、
スターやフォローをしていただけると励みになります。
また、続編として Nginx のセキュリティ設計 / HTTP/2 の内部 / QUIC の実装解説 なども書く予定です。