Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introducing RFC9111 / YAPC::Fukuoka 2025

Introducing RFC9111 / YAPC::Fukuoka 2025

Avatar for Ken’ichiro Oyama

Ken’ichiro Oyama

November 13, 2025
Tweet

More Decks by Ken’ichiro Oyama

Other Decks in Technology

Transcript

  1. 少し実⽤的で⼩さなOSSを書くのが趣味 • GitHub: @k1LoW • X: @k1LoW • SWE at

    Tailor Inc. / Fukuoka.go ⼩⼭健⼀郎 ⾃⼰紹介 2 Ken'ichiro Oyama
  2. • 参考⽂献紹介 • HTTPキャッシュ ◦ RFC7234 ◦ RFC9111 • github.com/2manymws/rc

    • RFC9111 ◦ キャッシュの格納 ◦ キャッシュの利⽤ Agenda 4
  3. • https://gihyo.jp/book/2021/978-4-297-11925-6 • RFC9111が公開される前の書籍。しかしドラフ ト時の内容に⾔及していて実質RFC9111 • HTTPキャッシュの理解のためには正直この書籍 だけで⼗分   5

    "Web配信の技術 ―HTTPキャッシュ‧リバースプロキシ‧CDNを活⽤する" 参考⽂献紹介 HTTPキャッシュ、リバースプロキシ、CDNなどWeb開発で ⼤切な「配信」の技術。 重要な技術ながら、現場では知⾒のあるエンジニアが少な く、なんとなくで運⽤されていたり、導⼊が遅れていたり します。 本書では、HTTPキャッシュの基礎から解説し、⼀冊でしっ かり配信が学べます。 速くて落ちないWebサイト∕Webサービス∕Web APIの実 現はもちろん。キャッシュ事故やセキュリティ上の問題を 防ぐのにも役⽴ちます。
  4. • RFC2616を廃⽌ • 2014年6⽉ に公開 • Proposed Standard HTTPキャッシュ 8

    RFC7234 The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document defines HTTP caches and the associated header fields that control cache behavior or indicate cacheable response messages.
  5. • RFC7234を廃⽌ • 2022年6⽉ に公開 • Internet Standard HTTPキャッシュ 9

    RFC9111 The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document defines HTTP caches and the associated header fields that control cache behavior or indicate cacheable response messages. This document obsoletes RFC 7234.
  6. • NGINX ... 公式ドキュメントにRFC参照の明⽰なし • Envoy ... RFC7234参照 ◦ "HTTP

    Cache only caches responses with enough data to calculate freshness lifetime as per RFC7234" ◦ https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/cache_filter • Apache mod_cache ... RFC2616 参照 ◦ "RFC 2616 compliant HTTP caching filter" "RFC 2616 allows for the cache to return stale data while the existing stale entry is refreshed" ◦ https://httpd.apache.org/docs/current/mod/mod_cache.html • Varnish ... RFC7234等を参照。RFC参照ページあり。ただし主要なキャッシュ動作についてRFC番号の明 ⽰なし ◦ https://varnish-cache.org/rfc/ HTTPキャッシュ実装の参照RFCの現状 HTTPキャッシュ 10 プロキシサーバー(?)
  7. • Fastly ... RFC9111 参照 ◦ "Cache-Control response directives are

    defined by section 5.2.2 of RFC 9111" ◦ https://www.fastly.com/documentation/guides/full-site-delivery/caching/about-cache-control- headers/ • Cloudflare ... RFC7234 / RFC2616参照 ◦ "aim to strictly adhere to RFC 7234" / "Expires header ... use Greenwich Mean Time (GMT) as stipulated in RFC 2616" ◦ https://developers.cloudflare.com/cache/concepts/cache-control/ • Akamai ... RFC7234 参照 ◦ "enables honoring particular Cache-Control header directives from the origin and supports all official RFC 7234 directives except for no-transform" (enhancedRfcSupportオプション) ◦ https://techdocs.akamai.com/property-mgr/reference/latest-caching HTTPキャッシュ実装の参照RFCの現状 HTTPキャッシュ 11 CDN
  8. • RFC7234-RFC9111間で破壊的変更が少ない ◦ 共有キャッシュにおける⼤きめの変更はmust-understandディレクティブの追加とWarningヘッ ダーの廃⽌くらい • RFC9111は「定義をはっきりさせた」という印象。そして、そもそも定義の揺れは現実世界ではある程度 受け⼊れられていた ◦ ディレクティブが競合する場合の⽅針の明確化や、publicおよびprivateディレクティブの明確化など

    • そもそも世の中にはHTTPキャッシュについての独⾃実装や独⾃設定が溢れていてRFC完全準拠のメリット が⼩さい ◦ 採⽤するプロキシサーバーやCDNの実装に応じて柔軟に対応している状況 「なぜ未だにRFC7234の参照が多いのか」についての私⾒ HTTPキャッシュ 12
  9. • rc is a response cache middleware for cache. ◦

    https://github.com/2manymws/rc • type rc.Cacher interface を満たす実装を⼊⼒にレスポンスキャッシュの HTTP middleware func(next http.Handler) http.Handler を作成するパッケージ github.com/2manymws/rc 14
  10. • ただし、リクエストディレクティブに対する挙動は意図的にほぼ未実装 • github.com/2manymws/rc はオリジンのためのキャッシュ機構として使⽤することを想定しているため リクエストディレクティブ github.com/2manymws/rc 16 クライアントから max-age=0

    を指定してリクエストを⾏ったとしても CDNが正しく解釈してオリジンに 検証する動作を筆者はみたことがありません。 (中略) ただ、リクエストヘッダの Cache-Control については、 名前に反して経路上のキャッシュでは考慮す る必要がない のです。 『Web配信の技術』. "Column リクエスト時にもCache-Controlは送信される". p82 (※強調は発表者)
  11. • HTTP middleware handlers and related packages for Go •

    主に特殊な⽤途なHTTP middlewareやその周辺パッケージを提供している ◦ rp ... rp is a reverse proxy package for multiple domains and multiple upstreams. ▪ https://github.com/2manymws/rp ▪ 複数ドメイン複数アップストリーム を実現するリバースプロキシ ◦ rl ... rl is a rate limit middleware for multiple limit rules. ▪ https://github.com/2manymws/rl ▪ 複数ルールのレートリミット を実現するHTTP middleware • Sliding Window Counterパターン ◦ mm ... mm is a middleware-middleware for multiple rules. ▪ https://github.com/2manymws/mm ▪ 動的なHTTP middleware適⽤ルール を実現するHTTP middleware github.com/2manymws org github.com/2manymws/rc 17
  12. • type rc.Handler interface のうち ◦ Storable() が「キャッシュの格納」を実装 ◦ Handle()

    が「キャッシュの利⽤」を実装 (再掲)github.com/2manymws/rc RFC91111 21
  13. • そもそも理解可能なメソッドなのか。ステータスコー ドが >= 200 かどうか。 • Cache-Control: no-store といった

    格納不可かど うか • Cache-Control: public といった 明⽰的なキャッ シュ許可ディレクティブがあるかどうか RFC9111 - キャッシュの格納 25 必須条件(格納禁⽌条件)チェック  
  14. • RFC7234では Cache-Control: no-store はキャッシュ格納不可 • RFC9111では Cache-Control: no-store であっても、

    must-understand ディレクティブが存在し、 理解可能なステータスであれば no-store を無視してキャッシュすることが可能 • 新しいキャッシュ可能なステータスコードや、特別なキャッシング動作を持つ既存のステータスコードが 導⼊された際に、古いキャッシュ機構が予期せぬキャッシュ格納を⾏うのを防ぎつつ、新しいキャッシュ 機構がキャッシュ格納できるようにする⽬的 ◦ 新ステータスコードを理解不可な場合 ... no-store ということで、キャッシュしない ◦ 新ステータスコードを理解可能な場合 ... no-store を無視して、後続のキャッシュ判定フローに乗 せて判定する must-understand
 RFC9111 - キャッシュの格納 26
  15. RFC9111 - キャッシュの格納 27 格納許可条件チェック   • Cache-Control のディレクティブや Expires

    ヘッダを確認 ◦ 両ヘッダがなくてもヒューリスティックに キャッシュに格納することがある
  16. • 基本的には「Freshならキャッシュを再利⽤して良い。Staleなら条件付きで再利⽤して良い」 • Fresh ... キャッシュに保存されているレスポンスが、オリジンサーバーに問い合わせることなく(検証な しで)クライアントのリクエストに対して再利⽤できる状態にあること • Stale ...

    キャッシュに格納されているレスポンスが、そのFreshness Lifetime(鮮度寿命)を超過している 状態。 Freshの逆 。 Freshではない状態 • Freshness Lifetime ... オリジンサーバーによってレスポンスが⽣成されてから、いつまで検証なしで再利 ⽤して良いかを⽰す期間 Fresh と Stale RFC9111 - キャッシュの利⽤ 30
  17. • RFC9111では、異なるディレクティブ間で意味が競合する場合の優先順位について明確な指針が⽰されて いる • より厳しいディレクティブが尊重されるべき ◦ If directives conflict (e.g.,

    both max-age and no-cache are present), the most restrictive directive should be honored. • Cache-Control: max-age=3600, no-cache とある場合、 no-cache のほうが制限が厳しいので採⽤ • RFC7234では直接的な原則を定めた条項はない 競合するディレクティブの明確化 RFC9111 - キャッシュの利⽤ 36
  18. • This is a test suite for the behaviours of

    HTTP caches, including browsers, proxy caches and CDNs. • https://cache-tests.fyi/ ◦ https://github.com/http-tests/cache-tests • RFC9111を参照しているテストスイート ◦ HTTPキャッシュはその性質上、最適化⼿段である。実装は全てをキャッシュする必要はない。ただ し、キャッシュを⾏う場合、その動作は仕様書(RFC9111)によって制約される。(発表者訳) • ローカルでもテストが可能(!!!) Tests for HTTP Caches RFC91111 41
  19. • PASS率 58.1% (212/365)。思ったよりも低い!! ◦ v0.14.0 • 失敗しているテスト概要(⼀部) ◦ Staleレスポンスの対応が不⼗分

    ▪ ETag や Last-Modified を使った条件付きリクエストの⽣成が不⼗分 ◦ オリジンからの304 Not Modifiedレスポンスによるキャッシュ更新が未対応 ▪ 条件付きリクエストが不⼗分なため ◦ リクエストディレクティブに未対応 ◦ Rangeリクエストに未対応 • 全てのテストをPASSすれば良いものではないらしいし、失敗しているテストを⾒る限りゲートウェイ キャッシュとしての共有キャッシュ機構としては⼤きな問題にはならなそうだが厳しい Tests for HTTP Caches RFC91111 42 github.com/2manymws/rc/rfc9111 をテストしてみた
  20. • RFC9111の「キャッシュの格納」と「キャッシュの使⽤」についてフローチャートを元に紹介した ◦ 「キャッシュの格納」は "3. Storing Responses in Caches" ▪

    https://www.rfc-editor.org/rfc/rfc9111#section-3 ◦ 「キャッシュの利⽤」は "4. Constructing Responses from Caches" ▪ https://www.rfc-editor.org/rfc/rfc9111#section-4 • 発表者はRFC9111を参照した共有キャッシュHTTPミドルウェア github.com/2manymws/rc を開発した ◦ RFC7234と⽐べて仕様が明確になっているので相対的に実装しやすい ▪ 「RFC7234からの変更」は "Appendix B. Changes from RFC 7234" • https://www.rfc-editor.org/rfc/rfc9111#appendix-B • 皆さんのTests for HTTP Caches PASS率58.1%以上の実装をお待ちしています!! まとめ 44
  21. 以下の優先順位でFreshness Lifetime( freshness_lifetime )を決定 1. 共有キャッシュかつs-maxageディレクティブあり: s-maxageの値を使⽤ 2. max-ageディレクティブあり: max-ageの値を使⽤

    3. Expiresヘッダーあり: Expires - Dateの値を使⽤ 4. 明⽰的な期限なし: ヒューリスティック(推測的)な⽅法を適⽤可能 freshness_lifetime > current_age かどうかでFreshかStaleを決定 freshness_lifetimeの計算 Appendix 48
  22. 以下の⼿順でcurrent_ageを計算 1. apparent_age: max(0, response_time - date_value)
 a. サーバーがレスポンスを⽣成した時刻と受信時刻の差 2.

    response_delay: response_time - request_time
 a. ネットワーク遅延時間 3. corrected_age_value: age_value + response_delay
 a. Ageヘッダーの値にネットワーク遅延を加算 4. corrected_initial_age: max(apparent_age, corrected_age_value)
 a. 2つの計算⽅法の⼤きい⽅を採⽤(保守的なアプローチ) 5. resident_time: now - response_time
 a. レスポンスがローカルに保存されている時間 6. current_age: corrected_initial_age + resident_time
 a. 最終的な経過時間 current_ageの計算 Appendix 49