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?

Nginx・Linux・QUIC・io_uring の内部構造を体系的に理解するための完全ガイド

0
Posted at

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
  1. io_uring + Nginx の将来像
    Nginx は現在 epoll ベースだが、
    将来的には io_uring による 完全非同期 I/O が可能。
  • epoll → io_uring への移行可能性
  • 完全非同期化
  • sendfile の置き換え候補

置き換えポイント

  • accept
  • read/write
  • sendfile の代替
  • timerfd との統合

課題

  • Nginx のイベントモデルが epoll 前提
  • io_uring は「I/O 完了通知」モデル
  • 大規模改修が必要
  1. 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 の内部構造を深く理解するための
永久保存版のリファレンスになれば幸いです。

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?