Slide 1

Slide 1 text

CDN導入が一般になったからこそ 復習したい事故らない・安定運用のポイント 株式会社グリー 開発本部 インフラストラクチャ部 田中 祥平(@xcir)

Slide 2

Slide 2 text

田中 祥平(@xcir) ● いわなちゃんさんと呼ばれてます ● グリーでインフラエンジニアをやってます ● 2021年にWeb配信の技術という本を書きました ● 今回の勉強会のタイトルにビビっています ○ イオン×ZOZO×『Web配信の技術』著者が語るパフォーマンスチューニング ...

Slide 3

Slide 3 text

配信本が出て 4年 ● 執筆は2018年からなので書き直したいことや追記したいことはでてくる ● HTTPキャッシュの新RFCが出た(RFC9111) ● CDN業者が配信以外の機能を続々出してきた ● CDNを使うことが特別でなくなった ● など

Slide 4

Slide 4 text

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 基本は変わってない

Slide 5

Slide 5 text

CDN業者が配信以外の機能を続々だしてきた ● Akamaiの収益の2/3がセキュリティとクラウドコンピューティング ● 本を書いた当時は配信が収益の 2/3だった ● FastlyはAI AcceleratorというLLMの結果をキャッシュするサービスを開始 ● キャッシュキーの取り扱いまったく違うものをキャッシュしている ● Cloudflareはよりコンピューティングの機能を強化 全般的にコンピューティング、もしくはその周辺機能を強化している

Slide 6

Slide 6 text

CDN業者が配信以外の機能を続々だしてきた ● CDN業者は自身のことをCDNであるとはあまり言っていない ● 〇〇プラットフォームであると言っている ○ Intelligent Edge Platform(Akamai), Edge Cloud Platform(Fastly), ● 要は地球規模で分散されたネットワーク品質の良いコンピューティングのプラットフォーム ● 今なら基本的に単一リージョンであることも付け加えたい ● プラットフォーム上に様々な新機能が増えていく ● キャッシュだったりセキュリティだったり・・・ CDNの本質(プラットフォーム上の一機能 )は変わっていない 分散されたネットワーク品質の良い コンピューティングプラットフォーム HTTPキャッシュ セキュリティ … CDN

Slide 7

Slide 7 text

CDNを使うことが特別ではなくなった ● そもそもの執筆した経緯がとあるキャッシュ事故で見かけた呟きや記事 ● 動的コンテンツをCDNでキャッシュするなんて・・・( !?) ● 社内コンフルで書く→ブログに転記→技評の人から声がかかる →本が出る ● 今ではCDNを導入はメジャーな手段 ● セキュリティ対策だったり、負荷軽減だったり理由は様々だが以前とは状況が違う ● 配信以外の機能が増えてよりロジックを置けるようになったのも一因 ● しかしながらコンスタントに事故は発生している ● 今年も音楽系の通販サイトでキャッシュ事故が発生 ● 本を書いた理由の一つが導入事故を減らしたかったからなので悲しい 導入して事故るのは(悲しいけれど)変わってない

Slide 8

Slide 8 text

配信はいろいろ変わったけれども 基本は変わっていない

Slide 9

Slide 9 text

なのでもう一度復習して 導入から運用まで安定したパフォーマンスを目指そう

Slide 10

Slide 10 text

なぜCDN導入で事故るのか コンテンツ生成に必要な入力すべてをキーに設定していない

Slide 11

Slide 11 text

クライアント・サーバの 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さんこんにちわ …. オリジン

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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 キャッシュ

Slide 14

Slide 14 text

なぜキャッシュキーを適切に設定できないのか ● 身もふたもないことを言うと意識していないだけだと思いますが・・・ ● そもそもCDNにおけるデフォルトのキャッシュキーを把握していない ● 大体のところはURL ● プログラムの引数とは違って列挙されているわけではない ● キャッシュをするなら正規化が必要という意識がない とはいえ不要なヘッダをすべて消すのは過激なのでリスクが高いところに絞ってフィルタしよう //キャッシュするなら関数名と全引数をキーに含める function foo($a, $b, $c){ return $a.$b.$c; }

Slide 15

Slide 15 text

大事故にならないために ● 個人と紐づけできるデータが含まれてそうなヘッダを消す ● Cookie, Authorization… ● 使う場合はキーに含めてそれだけオリジンに流す ● アプリで作りによるのでこれだけ消せばいいというわけではない ● 例えば端末種別(PC/SP)で結果を変えるのはよくある ○ その場合は正規化してキーに含めると効率が良くなる ● X-HTTP-Method-OverrideはGCSオリジンの時は普通に危ないので消すのがおススメ ● 消しておけばそれを元にコンテンツ作成できないのでフェイルセーフ ● 画面はバグるかもしれないが個人情報流出はしない 基本消しておいて必要なパスにはキーに追加して通す

Slide 16

Slide 16 text

クライアント・サーバの 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さんこんにちわ …. オリジン

Slide 17

Slide 17 text

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 ① ② ③ ④ ⑤ オリジン

Slide 18

Slide 18 text

Set-Cookieも危ない ● セッション・トークンをキャッシュしてしまうと大事故 ● キャッシュされた人のmypageが見れたりする ● 本来の持ち主でも、古いセッションを使って期限切れみたいなバグが起きる ● Set-Cookie全部を消す必要はないがセッション・トークンは確実に消しておく ● 例えば特定ページを経由したら固定値をセットするみたいなものであれば問題はない ● とはいえキャッシュに含まれなければいいわけで CDNで処理するのはOK ● 先に触れたように各社コンピューティング機能を強化している

Slide 19

Slide 19 text

ここまでやれば個人情報が漏れることはない(はず)

Slide 20

Slide 20 text

なぜ運用で事故るのか 静的なリソースをキャッシュするだけで 済んだ時代の意識が抜けない

Slide 21

Slide 21 text

サイトは生き物 ● 以前と違いCDN側にロジックを置くことが多くなった ● /cssや/imgのパスだけの設定しておしまいで済む時代は終わった ● キャッシュキーの操作も普通に行うようになった ● サイトは常に開発が走っていて生き物 ● 設定頻度が高くなった ● 複雑度もあがり設定をポチポチしたり curlで叩いて確認で済む時代は終わった ● CDNでもテストコードを書きましょう ● 自分はvarnishtestにshellを被せてやっています ● https://labs.gree.jp/blog/2024/02/23009/ とにかくテストしましょう

Slide 22

Slide 22 text

なぜ運用で事故るのか 軽率にパージをしてオリジンが死んでしまう

Slide 23

Slide 23 text

軽率にパージをするとサイトが死ぬ ● CDNを入れる目的はいろいろあるが負荷軽減もその一つ ● 以前と比較して生成コストが高いコンテンツをキャッシュするようになった ○ 静的が主の時代とは違う ○ 全消しでなく特定のパスでも高コストならオリジンは死ぬ ● ヒット率98%だとパージでリクエスト数が 50倍ですがスケール間に合いますか? ● パージに耐えるにはいくつかの方法が存在 ● 事前にスケールするなどオリジン強化 ● パージを分割する ○ URL構造でシャーディングをしてパス前方一致で消す (item/1/, item/2/…) ○ キャッシュタグを利用して想定されうるパージ単位や、シャーディングをする CDNを導入するならどのようにキャッシュを消すのか考えておこう

Slide 24

Slide 24 text

キャッシュタグとは ● いくつかの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

Slide 25

Slide 25 text

パージの方法も意識しよう ● キャッシュの消し方は2種類存在 ● Invalidate ○ キャッシュ期限切れ状態にする ■ 次回リクエスト時に if-modified-sice/if-none-matchでの再検証が走る ● Delete ○ キャッシュを削除する ● 基本はInvalidateで問題ないが次の場合は Deleteが必要 ● ETag/Last-Modifiedが存在して同じ値がレスポンスされる(再検証で有効になる) ○ キャッシュが破損している場合 ■ 本当に稀なんですが S3オリジンで1か月前に遭遇しました・・・ ○ アプリの作りでそうなっている場合

Slide 26

Slide 26 text

他にも運用のポイントはたくさんありますが 昔の意識でCDNを使うとハマるポイントはこのあたり

Slide 27

Slide 27 text

まとめ ● パフォーマンスを向上させるために CDNを入れるのにそれで事故るのはもったいない ● 全面的にいれることでひとたび事故が起きると甚大な被害が起きる ● 以前に比べてCDNの活用は進んできたが最低限 意識すべきことは変わらない ● キャッシュキーの適切な設定 ● 不要なヘッダの削除 ● CDNの活用範囲が広がったからこそ 認識を変える必要がある ● 以前より複雑かつ設定変更の頻度が上がったからこそテストを活用する ● 生成コストの高いコンテンツをキャッシュしているならパージの負荷上昇を意識する 変わらないこと変わったことありますが CDNで安定したパフォーマンスを維持していきましょう