$30 off During Our Annual Pro Sale. View Details »

CDN導入が一般になったからこそ 復習したい事故らない・安定運用のポイント

CDN導入が一般になったからこそ 復習したい事故らない・安定運用のポイント

イオン×ZOZO×『Web配信の技術』著者が語るパフォーマンスチューニング:60分で掴む劇的改善術で発表された資料です。
https://aeon.connpass.com/event/362806/

Avatar for gree_tech

gree_tech PRO

August 26, 2025
Tweet

More Decks by gree_tech

Other Decks in Technology

Transcript

  1. HTTP Caching (RFC 9111) • 新要素もあるがブラッシュアップと曖昧な部分の整理が多い • 仕様としてはあるけどもういいよねで非推奨となった Pragmaなど •

    重複定義(複数のExpiresやmax-age)や競合定義(max-ageとno-cacheの同時指定)の取り扱い • Ageヘッダが複数あった場合の取り扱い方 • など • CDNを使うなら(他の改訂された HTTP関連のRFCも合わせて) 一度読んでおくのをお勧め • ただしCDNの実装がすべてRFC準拠ではないので勘違いしないようにしましょう ◦ この動きをするという思い込みで事故が起きる ので必ずテストしよう • 議論の一部はGithubのissueで見れるので変更の文脈が分かるので読みやすい ◦ https://github.com/httpwg/http-core/issues?q=is%3Aissue+is%3Aclosed+label%3Acaching+sort%3Acreated-asc 基本は変わってない
  2. CDN業者が配信以外の機能を続々だしてきた • Akamaiの収益の2/3がセキュリティとクラウドコンピューティング • 本を書いた当時は配信が収益の 2/3だった • FastlyはAI AcceleratorというLLMの結果をキャッシュするサービスを開始 •

    キャッシュキーの取り扱いまったく違うものをキャッシュしている • Cloudflareはよりコンピューティングの機能を強化 全般的にコンピューティング、もしくはその周辺機能を強化している
  3. CDN業者が配信以外の機能を続々だしてきた • CDN業者は自身のことをCDNであるとはあまり言っていない • 〇〇プラットフォームであると言っている ◦ Intelligent Edge Platform(Akamai), Edge

    Cloud Platform(Fastly), • 要は地球規模で分散されたネットワーク品質の良いコンピューティングのプラットフォーム • 今なら基本的に単一リージョンであることも付け加えたい • プラットフォーム上に様々な新機能が増えていく • キャッシュだったりセキュリティだったり・・・ CDNの本質(プラットフォーム上の一機能 )は変わっていない 分散されたネットワーク品質の良い コンピューティングプラットフォーム HTTPキャッシュ セキュリティ … CDN
  4. CDNを使うことが特別ではなくなった • そもそもの執筆した経緯がとあるキャッシュ事故で見かけた呟きや記事 • 動的コンテンツをCDNでキャッシュするなんて・・・( !?) • 社内コンフルで書く→ブログに転記→技評の人から声がかかる →本が出る •

    今ではCDNを導入はメジャーな手段 • セキュリティ対策だったり、負荷軽減だったり理由は様々だが以前とは状況が違う • 配信以外の機能が増えてよりロジックを置けるようになったのも一因 • しかしながらコンスタントに事故は発生している • 今年も音楽系の通販サイトでキャッシュ事故が発生 • 本を書いた理由の一つが導入事故を減らしたかったからなので悲しい 導入して事故るのは(悲しいけれど)変わってない
  5. クライアント・サーバの HTTP通信を考えて見よう POST /login HTTP/1.1 Host: example.net HTTP/1.1 303 See

    Other … Set-Cookie: user=111 Set-Cookie: b=222 GET /banner HTTP/1.1 Host: example.net Cookie: user=111; b=222 HTTP/1.1 200 OK … AAAさんこんにちわ …. オリジン
  6. HTTP/1.1 200 OK … AAAさんこんにちわ …. クライアント・サーバの HTTP通信を考えて見よう GET /banner

    HTTP/1.1 Host: example.net Cookie: user=111; b=222 HTTP/1.1 200 OK … AAAさんこんにちわ …. キャッシュキーにコンテンツを生成するのに必要なものを含めないと事故る CDN GET /banner HTTP/1.1 Host: example.net Cookie: user=xxx; b=yyy HTTP/1.1 200 OK … AAAさんこんにちわ …. https://example.net/banner
  7. HTTP/1.1 200 OK … BBBさんこんにちわ …. HTTP/1.1 200 OK …

    AAAさんこんにちわ …. クライアント・サーバの HTTP通信を考えて見よう GET /banner HTTP/1.1 Host: example.net Cookie: user=111; b=222 HTTP/1.1 200 OK … AAAさんこんにちわ …. キャッシュキーにコンテンツを生成するのに必要なものを含めないと事故る CDN GET /banner HTTP/1.1 Host: example.net Cookie: user=xxx; b=yyy HTTP/1.1 200 OK … BBBさんこんにちわ …. https://example.net/banner user=111 https://example.net/banner user=xxx キャッシュ
  8. なぜキャッシュキーを適切に設定できないのか • 身もふたもないことを言うと意識していないだけだと思いますが・・・ • そもそもCDNにおけるデフォルトのキャッシュキーを把握していない • 大体のところはURL • プログラムの引数とは違って列挙されているわけではない •

    キャッシュをするなら正規化が必要という意識がない とはいえ不要なヘッダをすべて消すのは過激なのでリスクが高いところに絞ってフィルタしよう //キャッシュするなら関数名と全引数をキーに含める function foo($a, $b, $c){ return $a.$b.$c; }
  9. 大事故にならないために • 個人と紐づけできるデータが含まれてそうなヘッダを消す • Cookie, Authorization… • 使う場合はキーに含めてそれだけオリジンに流す • アプリで作りによるのでこれだけ消せばいいというわけではない

    • 例えば端末種別(PC/SP)で結果を変えるのはよくある ◦ その場合は正規化してキーに含めると効率が良くなる • X-HTTP-Method-OverrideはGCSオリジンの時は普通に危ないので消すのがおススメ • 消しておけばそれを元にコンテンツ作成できないのでフェイルセーフ • 画面はバグるかもしれないが個人情報流出はしない 基本消しておいて必要なパスにはキーに追加して通す
  10. クライアント・サーバの HTTP通信を考えて見よう GET /foo HTTP/1.1 Host: example.net HTTP/1.1 200 OK

    … Set-Cookie: sess=111 Set-Cookie: b=222 GET /banner HTTP/1.1 Host: example.net Cookie: sess=111; b=222 HTTP/1.1 200 OK … AAAさんこんにちわ …. オリジン
  11. HTTP/1.1 200 OK … Set-Cookie: sess=111 Set-Cookie: b=222 …. クライアント・サーバの

    HTTP通信を考えて見よう Set-Cookieも危ない CDN https://example.net/foo GET /foo HTTP/1.1 Host: example.net HTTP/1.1 200 OK … Set-Cookie: sess=111 Set-Cookie: b=222 GET /foo HTTP/1.1 Host: example.net HTTP/1.1 200 OK … Set-Cookie: sess=111 Set-Cookie: b=222 ① ② ③ ④ ⑤ オリジン
  12. Set-Cookieも危ない • セッション・トークンをキャッシュしてしまうと大事故 • キャッシュされた人のmypageが見れたりする • 本来の持ち主でも、古いセッションを使って期限切れみたいなバグが起きる • Set-Cookie全部を消す必要はないがセッション・トークンは確実に消しておく •

    例えば特定ページを経由したら固定値をセットするみたいなものであれば問題はない • とはいえキャッシュに含まれなければいいわけで CDNで処理するのはOK • 先に触れたように各社コンピューティング機能を強化している
  13. サイトは生き物 • 以前と違いCDN側にロジックを置くことが多くなった • /cssや/imgのパスだけの設定しておしまいで済む時代は終わった • キャッシュキーの操作も普通に行うようになった • サイトは常に開発が走っていて生き物 •

    設定頻度が高くなった • 複雑度もあがり設定をポチポチしたり curlで叩いて確認で済む時代は終わった • CDNでもテストコードを書きましょう • 自分はvarnishtestにshellを被せてやっています • https://labs.gree.jp/blog/2024/02/23009/ とにかくテストしましょう
  14. 軽率にパージをするとサイトが死ぬ • CDNを入れる目的はいろいろあるが負荷軽減もその一つ • 以前と比較して生成コストが高いコンテンツをキャッシュするようになった ◦ 静的が主の時代とは違う ◦ 全消しでなく特定のパスでも高コストならオリジンは死ぬ •

    ヒット率98%だとパージでリクエスト数が 50倍ですがスケール間に合いますか? • パージに耐えるにはいくつかの方法が存在 • 事前にスケールするなどオリジン強化 • パージを分割する ◦ URL構造でシャーディングをしてパス前方一致で消す (item/1/, item/2/…) ◦ キャッシュタグを利用して想定されうるパージ単位や、シャーディングをする CDNを導入するならどのようにキャッシュを消すのか考えておこう
  15. キャッシュタグとは • いくつかのCDNで使えるタグベースのパージ ◦ Akamai, Cloudflare, Fastly, Tencentなどで使える • オリジンからのヘッダなどでタグを指定することでグループ化ができる

    ◦ Cache-Tag: avatar_1, image_2, all_4 ◦ 消す場合はavatar_1のようなタグ指定で消す • 一番の利点はキャッシュキーと違いオブジェクトの関係が 1:nになる ◦ キャッシュキーは 1:1 ◦ 1キャッシュタグの指定で 100や200のオブジェクトを指定してパージすることができる • これを利用することで高コストでも比較的安全に分割パージを行える • 他にも便利に使える ◦ 動的サムネイル生成でタグを元ファイル名で設定 ▪ 元ファイル+サムネイルを一気に消せる user123.jpg user123_thumb1.jpg user123_thumb2.jpg Cache-tag: img_user123 user456_thumb1.jpg Cache-tag: img_thumb1
  16. パージの方法も意識しよう • キャッシュの消し方は2種類存在 • Invalidate ◦ キャッシュ期限切れ状態にする ▪ 次回リクエスト時に if-modified-sice/if-none-matchでの再検証が走る

    • Delete ◦ キャッシュを削除する • 基本はInvalidateで問題ないが次の場合は Deleteが必要 • ETag/Last-Modifiedが存在して同じ値がレスポンスされる(再検証で有効になる) ◦ キャッシュが破損している場合 ▪ 本当に稀なんですが S3オリジンで1か月前に遭遇しました・・・ ◦ アプリの作りでそうなっている場合
  17. まとめ • パフォーマンスを向上させるために CDNを入れるのにそれで事故るのはもったいない • 全面的にいれることでひとたび事故が起きると甚大な被害が起きる • 以前に比べてCDNの活用は進んできたが最低限 意識すべきことは変わらない •

    キャッシュキーの適切な設定 • 不要なヘッダの削除 • CDNの活用範囲が広がったからこそ 認識を変える必要がある • 以前より複雑かつ設定変更の頻度が上がったからこそテストを活用する • 生成コストの高いコンテンツをキャッシュしているならパージの負荷上昇を意識する 変わらないこと変わったことありますが CDNで安定したパフォーマンスを維持していきましょう