Web配信の技術
HTTPキャッシュ・リバースプロキシ・CDNを活用する

書籍の概要

この本の概要

HTTPキャッシュ,リバースプロキシ,CDNなどWeb開発で大切な「配信」の技術。
重要な技術ながら,現場では知見のあるエンジニアが少なく,なんとなくで運用されていたり,導入が遅れていたりします。
本書では,HTTPキャッシュの基礎から解説し,一冊でしっかり配信が学べます。

速くて落ちないWebサイト/Webサービス/Web APIの実現はもちろん。キャッシュ事故やセキュリティ上の問題を防ぐのにも役立ちます。

こんな方におすすめ

  • CDNやリバースプロキシの導入に興味のあるアプリケーションエンジニア・インフラエンジニア
  • 配信技術を学びたいインフラエンジニア
  • Webサービスを高速化させたいフロントエンドエンジニア

この書籍に関連する記事があります!

Web配信の技術 ~キャッシュとは
新型コロナの影響もあり,SNS上で過剰在庫を買ってほしいといったECサイトの投稿を見かけるようになりました。

本書のサンプル

本書の一部ページを,PDFで確認することができます。

目次

第1章 はじめに

  • 1.1 本書の対象と目的
  • 1.2 本書の構成
  • 1.3 下準備

第2章 配信の基礎

  • 2.1 配信のとらえ方
    • 2.1.1 配信の根幹
  • 2.2 標準仕様でやりとりする
    • Column RFCのMUST/SHOULD―RFC 2119
    • 2.2.1 配信の原則
  • 2.3 配信の経路
    • 2.3.1 ブラウザでWebページを表示するまで
    • 2.3.2 インターネットアクセス時の経路を体験する
    • Column tracerouteで前後するRTT
    • Column 帯域・通信速度・レイテンシ
    • Column 帯域と通信速度の違いを理解する
    • Column プロトコルによるレイテンシへの影響
    • Column 5Gはどこを高速化するのか
  • 2.4 配信をより高速なものにするために
    • 2.4.1 配信最適化のためになにができるのか
    • 2.4.2 配信経路の最適化
    • 2.4.3 クライアントとサーバーでの最適化
    • Column Webサイトのチューニング
  • 2.5 キャッシュの格納場所による分類
    • 2.5.1 クライアントのローカルキャッシュ
    • 2.5.2 経路上のキャッシュ
    • Column CDNの割り振りのしくみ
    • Column EDNS Client Subnet(ECS)―RFC 7871
    • 2.5.3 ゲートウェイ(サーバー/オリジン側)のキャッシュ
  • 2.6 private/sharedキャッシュ
    • 2.6.1 キャッシュの位置とprivate/shared
    • 2.6.2 private/sharedキャッシュの注意点
  • 2.7 どこでどうキャッシュすべきか
    • 2.7.1 キャッシュは誰が管理しているのか
    • Column CDNとゲートウェイキャッシュの違い

第3章 HTTPヘッダ・設定とコンテンツの見直し

  • 3.1 HTTPヘッダの重要性
    • 3.1.1 実際のサイトのヘッダを見る
    • 3.1.2 ヘッダとどう付き合うべきか
    • Column Apacheでのヘッダ操作
  • 3.2 HTTPメッセージ
    • 3.2.1 開始行―RFC 7230\#3.1
    • 3.2.2 ヘッダ―RFC 7230\#3.2
    • 3.2.3 ボディ―RFC 7230\#3.3
    • 3.2.4 HTTP/2でのHTTPメッセージ
  • 3.3 ステータスコードと説明句―RFC 7231\#6
    • Column 暫定応答の1xxと最終応答の1xx以外
    • 3.3.1 代表的なステータスコード
    • Column Status Code 418
  • 3.4 HTTPとキャッシュ
    • 3.4.1 キャッシュを行う・使う条件
  • 3.5 Cache-Controlによるキャッシュ管理
    • Column リクエスト時にもCache-Controlは送信される
    • 3.5.1 キャッシュの保存方法を指定(未指定/public/private)
    • Column キャッシュの仕様改定
    • 3.5.2 キャッシュの使われ方を指定する(no-store, no-cache)
    • 3.5.3 キャッシュの更新の方法を指定する(must-revalidate, proxy-revalidate, immutable)
    • 3.5.4 オブジェクトの取り扱いを指定する(no-transform)
    • Column 中間でのデータ変更(データセーバー・通信の最適化)
  • 3.6 Cache-Controlにおける期限指定
    • 3.6.1 キャッシュの期限と状態
    • 3.6.2 キャッシュは指定した期間保存されるとも限らない
    • 3.6.3 期限が切れたからといってすぐに消されない
    • 3.6.4 キャッシュの期限指定(max-age)
    • 3.6.5 経路上の期限指定(s-maxage)
    • 3.6.6 Staleキャッシュの利用方法を指定する(stale-while-revalidate/stale-if-error)
  • 3.7 Cache-ControlとExpiresヘッダ
  • 3.8 TTLが未定義時の挙動―RFC 7234\# 4.2.2
  • 3.9 キャッシュをさせたくない場合のCache-Control
    • Column 誤ったmax-ageの指定
    • Column キャッシュ不可なステータスコードをキャッシュする
    • Column 仕様はすべて実装されているとは限らない
  • 3.10 さまざまなリクエスト
    • 3.10.1 部分取得リクエスト(Range)―RFC 7233
    • 3.10.2 条件付きリクエスト(If-Modified-Sice/If-None-Match)―RFC 7232
  • 3.11 さまざまなヘッダ
    • 3.11.1 Vary―RFC 7234\#4.1
    • 3.11.2 Content-Type
    • Column 拡張子とMIMEタイプ
    • Column HTTP/2は使わなくてはいけないのか
    • Column HTTPのセマンティクスとRFC
    • Column HTTPを使う上でのベストプラクティスを紹介するRFC
  • 3.12 HTTPヘッダの不適切な設定で起きた事例
    • 3.12.1 Cache-Controlが未定義
    • 3.12.2 コンテンツが更新されてないにもかかわらずETagが変わる
    • Column ロードバランサーとロードバランシング
  • 3.13 ヘッダクレンジング
    • 3.13.1 ゲートウェイとオリジンサーバーを把握する
    • 3.13.2 どのようにコントロールするのか
  • 3.14 コンテンツのサイズ削減
    • 3.14.1 テキストが圧縮転送されていない
    • Column どこで圧縮するべきか
    • 3.14.2 ストレージサービスの圧縮漏れ
    • Column 圧縮は万能ではない
  • 3.15 適切なメディアの選択によるコンテンツの改善
    • 3.15.1 配信システムとファイルサイズ
    • 3.15.2 画像サイズが必要以上に大きくないか(サムネイル)
    • 3.15.3 bppを考える
    • 3.15.4 画像フォーマットは適切か
    • Column WebPと画像サイズ削減
    • Column JPEG画像の注意点
    • Column 外部サービスという選択肢
  • 3.16 問題点を調査する
    • 3.16.1 圧縮転送が有効になっていない
    • 3.16.2 ETag/Last-Modifiedがおかしい
    • 3.16.3 画像コンテンツが大きい
    • 3.16.4 キャッシュが有効に使われていない

第4章 キャッシュによる負荷対策

  • 4.1 キャッシュの構成・設定例
  • 4.2 さまざまな負荷とその事例
  • 4.3 負荷をさばくこととキャッシュ
    • 4.3.1 キャッシュ導入でどの程度パフォーマンスが向上したか
  • 4.4 キャッシュを使わない場合どうさばくか
  • 4.5 キャッシュを使う
    • Column ProxyやCDNはなぜ大量のリクエストをさばけるのか
    • 4.5.1 流入が増えるケースを追って考える
    • 4.5.2 キャッシュの役割
    • 4.5.3 静的ファイルの配信でもキャッシュは有効
  • 4.6 キャッシュ事故を防ぐ
    • 4.6.1 中間(Proxy/CDN)を信頼しすぎる
    • 4.6.2 オリジンを信頼しすぎる
  • 4.7 キャッシュ戦略・キャッシュキー戦略
    • 4.7.1 クライアントからのリクエストを実際に組み合わせる
    • 4.7.2 キャッシュキーとVaryのどちらに設定するか
    • 4.7.3 キャッシュフレンドリなパス設計
    • 4.8 キャッシュのTTLとキャッシュを消す
  • 4.9 キャッシュのTTL計算と再利用―RFC 7234\#4.2
    • Column 生成時刻とTTLを決める際の基準
    • 4.9.1 キャッシュの状態とStale
    • 4.9.2 TTL=0(max-age=0)とは何か
    • Column max-age=0とno-cacheの違い
    • 4.9.3 TTLの決め方
    • 4.9.4 もうひとつのキャッシュ エラーキャッシュ
  • 4.10 キャッシュの消去
    • 4.10.1 無効化と削除
    • 4.10.2 キャッシュ消去の注意点
    • 4.10.3 キャッシュ消去にどこまで依存するか
    • 4.10.4 サロゲートキー・キャッシュタグ

第5章 より効果的・大規模な配信とキャッシュ

  • 5.1 ヒット率だけによらない効率的なキャッシュの考え方
    • Column キャッシュアルゴリズム(LRU/LFU)
  • 5.2 どのようにリクエストを処理してレスポンスをするのか
    • 5.2.1 Proxy/CDNの機能を整理する
  • 5.3 RxReq―クライアントからのリクエストを受信する
    • 5.3.1 ACLの処理
    • 5.3.2 キャッシュキーの操作およびVaryで指定されたセカンダリキーに関連するヘッダの操作
    • 5.3.3 リクエストに含まれる情報に対する操作
    • 5.3.4 キャッシュ可否の判定
    • 5.4 Cache lookup―キャッシュヒットの判定を行う
    • 5.5 Wait for cache―キャッシュができるまで待つ
  • 5.6 TxReq―オリジンにリクエストを送信する
    • 5.6.1 複数のオリジンがある場合の選択
    • 5.6.2 キャッシュキーに影響を与えないオリジン問い合わせ時のホスト名・パス変更
    • 5.6.3 イベントの呼び出し数を減らしたい場合のヘッダ操作
  • 5.7 RxResp―オリジンからレスポンスを受信する
    • 5.7.1 キャッシュ可否の判定(2回目)
    • 5.7.2 TTLを設定する
    • 5.7.3 キャッシュするオブジェクトに対する操作
    • 5.7.4 キャッシュヒット判定に関係するVaryヘッダの変更
  • 5.8 TxResp―クライアントにレスポンスを送信する
    • 5.8.1 キャッシュは変わらないがクライアントごとにヘッダを変える必要がある(CORSなど)
    • 5.8.2 不要なヘッダの編集
  • 5.9 キャッシュキーをVaryで代用する
    • 5.9.1 Varyの利用例
    • 5.9.2 クライアントからの情報でセカンダリキー設定(RxReq)
    • 5.9.3 パスを変更する(TxReq)
    • 5.9.4 キャッシュに格納されるVaryを変更する(RxResp)
    • 5.9.5 クライアントに送るVaryに変更する(TxResp)
    • 5.9.6 Varyもキャッシュキーも編集できないときのクエリ文字列
    • 5.9.7 同一URLで複数のキャッシュを持つ方法の比較
  • 5.10 効果を高める対策
    • 5.10.1 ヒット率を上げる
    • Column 意図せず入るVary
    • 5.10.2 キャッシュするものを適切に選ぶ
    • 5.10.3 ローカルキャッシュがある状態で即時のコンテンツ更新(Cache Busting/no-cache)
    • 5.10.4 操作する場所を意識する
  • 5.11 動的コンテンツのキャッシュ
    • 5.11.1 動的コンテンツとは何か
    • 5.11.2 静的コンテンツ
    • 5.11.3 動的コンテンツ
    • 5.11.4 なぜ明確にTTLが決められないのか
  • 5.12 分割してキャッシュする
    • 5.12.1 キャッシュできるものとできないものを混ぜない
    • 5.12.2 異なるライフサイクルのものはなるべく混ぜない
    • 5.12.3 分離が困難だがとにかくキャッシュがしたい
    • 5.12.4 APIなどコードで生成されたコンテンツのキャッシュ
  • 5.13 Edge Side Includes(ESI)
    • 5.13.1 ESIのメリット
    • 5.13.2 ESIのしくみ
    • 5.13.3 ESIのデメリット
    • 5.13.4 応用的な使い方
  • 5.14 配信構成の工夫
    • 5.14.1 ストレージ
    • 5.14.2 Proxyの増設(スケールアウト)
  • 5.15 多段Proxy
    • 5.15.1 Proxyを増設すると何が起きるのか
    • 5.15.2 多段Proxyのメリット―一貫性
    • 5.15.3 1段方式の多段Proxy
    • 5.15.4 2段方式の多段Proxy
    • Column ハッシュをとってどのように振り分けを行うか
    • 5.15.5 どの方式の多段Proxyを採用すべきか
    • 5.15.6 多段Proxyのメリットをより深く理解する
    • 5.15.7 多段Proxyの注意点
    • Column キャッシュ巻き戻りの問題
    • Column max-ageが変動する時の注意
  • 5.16 障害時に正しくサーバーを切り離す(ヘルスチェック)
    • 5.16.1 ヘルスチェックを行う側の設定
    • 5.16.2 ヘルスチェックを受ける側の設定
  • 5.17 ドメインの分割
    • 5.17.1 動的コンテンツと静的コンテンツでドメインを分ける
    • 5.17.2 ZoneApex問題への対策

第6章 CDNを活用する

  • 6.1 なぜCDNが必要なのか―自前主義だけだと難しい
    • 6.1.1 自前主義がもたらす高コストとCDN
    • 6.1.2 CDN + 自社配信という選択肢
  • 6.2 CDNを使う前に
    • 6.2.1 CDNとは
    • Column オブジェクトストレージとCDN
    • 6.2.2 CDNだからできること
    • Column コラム ネットワークの品質が良いということはどういうことか
  • 6.3 CDNの選び方
    • 6.3.1 代表的なCDNの一覧
    • 6.3.2 どの地域に配信をするのか(海外・国内配信)
    • 6.3.3 ピーク帯域がどの程度あるのか CDNが対応できるか
    • 6.3.4 どのようにキャッシュを制御するのか
    • 6.3.5 HTTPSの取り扱い
    • 6.3.6 CDNのキャッシュの消去
    • 6.3.7 Apexドメインの扱い
    • 6.3.8 信頼できるのか
    • 6.3.9 CDNの多段キャッシュ
    • Column コンテンツの一貫性はどれほど必要なのか
  • 6.4 CDNを使うときに気をつけたいポイント
    • 6.4.1 キャッシュされない設定を調べる
    • 6.4.2 クエリ文字列の解釈について
    • 6.4.3 トラフィックなどの制限に注意
    • 6.4.4 コンテンツのサイズに注意
    • 6.4.5 Varyに注意
    • Column キャッシュ汚染DoS(CPDoS)
    • 6.4.6 CDNのデバッグ
    • Column CDNのヘッダと標準化
    • 6.4.7 CDNで隠したい情報をきちんと整理する
    • 6.4.8 ウォームアップ
  • 6.5 クライアントの近くでコードを動かす - エッジコンピューティング
    • Column 内部向けにCDNを使う - internal CDN
    • Column CDNのコスト
  • 6.6 CDNと障害
    • 6.6.1 CDNの障害
    • 6.6.2 問題の切り分け―それはCDNの障害なのか
    • 6.6.3 まずはmetricsを見てみる
    • 6.6.4 CDNの典型的な障害
    • 6.6.5 コンテンツのダウンロードが遅い
    • 6.6.6 キャッシュが壊れる
  • 6.7 動的コンテンツのキャッシュやCDN利用は危険なのか
    • Column マルチCDN
    • Column DNSブロッキングにかかる
    • Column 適切に設定しているのにキャッシュされない
  • 6.8 実際にCDNを設定する
    • 6.8.1 動的コンテンツの設定例

第7章 自作CDN(DIY-CDN)

  • 7.1 なぜCDNをつくるのか
    • 7.1.1 低予算
    • 7.1.2 ハイブリッドで使う
    • Column CDN自体を多段で使うときの注意
  • 7.2 低予算自作CDNの構成
    • 7.2.1 さまざまなことを諦める
    • 7.2.2 基本構成
    • Column VPSのプランをどう選ぶか
  • 7.3 自作CDNと外部CDNのハイブリッド構成
    • Column 低コスト運用からその先へ
  • 7.4 VCLでの設定例
    • 7.4.1 gatewayとcacheでの設定の目的
    • 7.4.2 リクエストの正規化
    • 7.4.3 キャッシュする場合のCookieなどの取り扱い
    • 7.4.4 TTLの設定
    • 7.4.5 オリジンへの振り分け
    • 7.4.6 ストレージの分割
    • 7.4.7 オリジンでの注意
    • 7.4.8 VCLサンプル

Appendix Varnishについて

  • A.1 Varnishのインストール
  • A.2 読みたい公式ドキュメント
  • A.3 Varnishのサポート体制
  • A.4 基本的なVCL
    • A.4.1 Varnishの起動方法と最小のVCLと考え方の基礎
    • A.4.2 文法の初歩
    • A.4.3 backendとdirector
    • A.4.4 サブルーチンとVCL変数
    • A.4.5 条件分岐・演算子・正規表現
    • A.4.6 VCLのデータ型と型変換
    • A.4.7 VCLを学ぶ
  • A.5 VCLを記述する際の注意点
    • A.5.1 "を含む文字列の指定方法
    • A.5.2 正規表現の取り扱い
    • A.5.3 デフォルトのVCLと同一名のVCLイベントの定義
    • A.5.4 VMOD
    • A.5.5 折り畳みをしてはいけないヘッダの扱い
  • A.6 テストの重要性―varnishtest
  • A.7 varnishのログと絞り込み方
    • A.7.1 VSLのグループ化
    • A.7.2 ログの絞り込み
  • A.8 そのほかのツールやコマンド
    • A.8.1 varnishstat
    • A.8.2 varnishadm
    • A.8.3 varnishtop
    • Column graceとkeepの取り扱い
    • Column VarnishとHTTPS

著者プロフィール

田中祥平(たなかしょうへい)

(いわなちゃん/xcir)
GREEで配信周りを引き受けるエンジニア。
配信全体に強く,特にVarnishに詳しい。
自社の大規模配信に加え,他社の中小規模サービスにアドバイザーとしても参加。幅広い経験を持つ。