ネットワーク層のチューニング
ネットワークはしばしば見落とされるボトルネックです。基本的な考え方を学びます。
┌─────────────────────────────────────────────────────────────┐
│ 「海外からだと遅いんです」 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 日本では速いのに、海外拠点からのアクセスが遅い。 │
│ コードもDBも同じなのに、なぜ? │
│ │
│ 答え: 光の速度には限界がある。 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 東京 → ニューヨーク: 片道 35ms、往復 70ms │ │
│ │ TCP接続 + TLS = 3往復 = 210ms(何もしてないのに) │ │
│ └─────────────── ──────────────────────────────────────┘ │
│ │
│ ネットワークは見落とされがちだが、 │
│ 特にグローバルサービスでは無視できない。 │
│ │
│ 物理法則は変えられない → 往復回数を減らす工夫が必要 │
│ │
└─────────────────────────────────────────────────────────────┘
このレイヤーのキー要素
┌─────────────────────────────────────────────────────────────┐
│ ネットワーク層で押さえるべきポイント │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ RTT │ │接続再利用│ │ 圧縮 │ │プロトコル│ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ ↓ ↓ ↓ ↓ │
│ 物理的距離 Keep-Alive gzip/brotli HTTP/2, /3 │
│ を縮める 接続プール で転送量削減 多重化 │
│ │
│ RTTは物理法則 → 減らせないなら「回数を減らす」 │
│ │
└─────────────────────────────────────────────────────────────┘
ネットワーク遅延の構成要素
総遅延 = 伝播遅延 + 伝送遅延 + 処理遅延 + キュー遅延
| 遅延の種類 | 原因 | 例 | 対策 |
|---|---|---|---|
| 伝播遅延 | 物理的な距離(光の速度の限界) | 東京-NY間: 往復140ms | CDN、リージョン配置 |
| 伝送遅延 | データサイズ ÷ 帯域幅 | 1MB / 100Mbps = 80ms | 圧縮、ペイロード削減 |
| 処理遅延 | ルーター、LB等での処理 | 数ms〜 | ホップ数削減 |
| キュー遅延 | 混雑による待ち時間 | 混雑時に増大 | 帯域確保、QoS |
注意: 伝播遅延は物理法則なので改善不可。往復回数を減らすことが重要。
接続のオーバーヘッド
症状: 初回リクエストだけ遅い、短いリクエストなのに時間がかかる
新規接続のコスト
| ハンドシェイク | RTT数 | RTT=10ms時 | RTT=100ms時 |
|---|---|---|---|
| TCP 3-way handshake | 1 RTT | 10ms | 100ms |
| TLS 1.2 handshake | 2 RTT | 20ms | 200ms |
| 合計 | 3 RTT | 30ms | 300ms |
何もデータを送る前に、これだけの時間がかかる。
対策
| 対策 | 効果 |
|---|---|
| Keep-Alive | 接続の再利用、ハンドシェイク不要に |
| 接続プーリング | 事前に接続を確立しておく |
| TLS 1.3 | ハンドシェイクを1 RTTに削減 |
| TLS Session Resumption | 再接続時のハンドシェイクを簡略化 |
ペイロードの最適化
症状: レスポンスサイズが大きい、帯域を圧迫している
圧縮
| 方式 | 圧縮率(テキスト) | CPUコスト | 備考 |
|---|---|---|---|
| gzip | 70-80%削減 | 中 | 広くサポート |
| brotli | 80-90%削減 | 高 | 静的ファイル向き |
| なし | - | なし | バイナリには不要 |
不要なデータを送らない
| 方法 | 内容 |
|---|---|
| フィールド選択 | 必要なフィールドだけ返す(GraphQL的発想) |
| ページネーション | 全件取得しない |
| キャッシュヘッダー | 変更がなければ304 Not Modified |
効率的なフォーマット
| フォーマット | サイズ | 可読性 | 用途 |
|---|---|---|---|
| JSON | 大 | 高 | 一般的なAPI |
| Protocol Buffers | 小 | 低 | gRPC、内部通信 |
| MessagePack | 中 | 低 | バイナリJSON |
HTTP/2 と HTTP/3
症状: 多数の小さなリクエストがある、接続数が多い
プロトコル比較
| 特性 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 多重化 | なし(1接続1リクエスト) | あり | あり |
| ヘッダー圧縮 | なし | HPACK | QPACK |
| 接続確立 | TCP + TLS = 3 RTT | TCP + TLS = 3 RTT | QUIC = 1 RTT |
| HOL Blocking | あり | TCP層であり | なし |
| トランスポート | TCP | TCP | UDP (QUIC) |
効果が大きいケース
| プロトコル | 効果が大きいケース |
|---|---|
| HTTP/2 | 多数の小さなリクエスト、API呼び出し |
| HTTP/3 | モバイル、高遅延環境、パケットロスが多い環境 |
CDN とエッジ
症状: 海外からのアクセスが遅い、静的ファイルの配信に時間がかかる
CDNの効果
| 経路 | レイテンシ |
|---|---|
| ユーザー(東京)→ オリジン(US) | 100ms以上 |
| ユーザー(東京)→ CDNエッジ(東京) | 5ms |
キャッシュヒット時は、ユーザーに最も近いエッジから即座に応答。
効果的なユースケース
| コンテンツ | CDN向き | 理由 |
|---|---|---|
| 静的ファイル(画像、CSS、JS) | ◎ | 変更がない、キャッシュ効果大 |
| 変更頻度の低いAPI | ○ | TTL設定で対応可能 |
| 動的コンテンツ | △ | キャッシュ困難、エッジコンピューティングで対応 |
| 認証が必要なAPI | × | キャッシュ不可、オリジン必須 |
まとめ
効果の大きいものから
| 優先度 | 対策 | 効果 |
|---|---|---|
| 1 | CDN/エッジ配置 | 大(物理的距離を縮める) |
| 2 | Keep-Alive/接続プール | 大(ハンドシェイク削減) |
| 3 | TLS 1.3 採用 | 中(1 RTT削減) |
| 4 | 圧縮(gzip/brotli) | 中(転送量削減) |
| 5 | HTTP/2以上の採用 | 中(多重化) |
心得
- RTTは物理法則: 減らせないなら往復回数を減らす
- 計測して判断: pingやtracerouteでボトルネックを特定
- トレードオフを理解: 圧縮はCPUを使う、CDNはキャッシュの整合性に注意