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

ふつうのWebアプリケーションとキャッシュ

 ふつうのWebアプリケーションとキャッシュ

2024/3/27 に開催された PHP勉強会 in 大阪 での発表資料です。
httpキャッシュと動的コンテンツの話

Yasuyuki Higa

March 27, 2024
Tweet

Other Decks in Programming

Transcript

  1. 自己紹介 名前: 比嘉 康至(ひが やすゆき) X(旧Twitter): @yh65743 勤務先: 株式会社ことば研究所 居住地:

    奈良(フルリモートで勤務しています) ❏ PHP ❏ React ❏ TypeScript 普段はこのあたりを使ってWebアプリケーション開発/ 保守やってます
  2. 今日話すこと • キャッシュとは何か • HTTPキャッシュの仕組み • 動的コンテンツのキャッシュ 今日話さないこと • Redis

    や APCu 等キャッシュ用ストレージの話 • DBキャッシュの話 • read-through, write-through といったキャッシュのアーキテクチャの話
  3. • うちのサイトそんなにPVないし。。。 → マナーの悪いbotが大挙して押し寄せてき ても大丈夫? → メディアに取り上げられたりして急なスパ イクがあっても耐えられる? → リクエスト毎に重めのクエリが発行される

    ようになってませんか? ふつうのWebアプリケーションとは • ブログ、ニュースサイト、ECサイト、求人サイト、etc… • PHPでよく作られるCMS的なアプリケーション
  4. LaravelのCache-Controlヘッダを見てみる • HTTPキャッシュの制御は Cache-Control ヘッダで行う • Laravel のCache-Control ヘッダ Cache-Control:

    no-cache, private なーんだ no-cache って書いてあるじゃん → no-cache はキャッシュしないという意味では ない!
  5. 条件付きリクエストの判定 リソースの最終更新日。 ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4" Last-Modified: Thu, 21 Mar 2024 17:38:20

    GMT キャッシュ制御のためにレスポンスに含まれているヘッダは Cache-Control 以外にもある。キャッシュが新鮮かどうか判定するために使われるのが ETag と Last-Modified ETag レスポンスとして返すコンテンツのバージョン番号のようなもの。何をETagとして返すか はサーバ側の実装次第だけどコンテンツの更新日時やコンテンツそのもののハッシュ等が 使われる。 Last-Modified
  6. 条件付きリクエストの判定 (ETagの場合) ブラウザは同じURLに対して再度リクエストする。そのとき If-None-Match というヘッダ を付与し、その値として覚えていた ETag の値を使用する If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

    サーバーは If-None-Match 付きのリクエストを受け取ると、ETag の値を計算したのと同 じ方法でリソースから値を得る。例えば、ファイルの更新日のハッシュを計算する。その結 果を If-None-Match の値と比較し、一致していたらステータスコード 304 Not Modified とヘッダ部分のみのレスポンスを返す ブラウザは304のレスポンスが得られたらキャッシュをレスポンスのボディとしてユーザー に表示する
  7. 条件付きリクエストの判定 (Last-Modifiedの場合) サーバーは初回リクエストしてきたブラウザに対して Cache-Control: no-cache Last-Modified: Tue, 26 Mar 2024

    00:40:43 GMT というヘッダのレスポンスを返す ブラウザはレスポンスをキャッシュする。Last-Modified の値も覚えておく。
  8. 条件付きリクエストの判定 (Last-Modifiedの場合) ブラウザは同じURLに対して再度リクエストする。そのとき If-Modified-Since という ヘッダを付与し、その値として覚えていた Last-Modified の値を使用する If-Modified-Since: Tue,

    26 Mar 2024 00:40:43 GMT サーバーは If-Modified-Since 付きのリクエストを受け取ると、リソースの最終更新日と If-Modified-Sinceの値を比較し、リソースが更新されていなければステータスコード 304 Not Modifiedとヘッダ部分のみのレスポンスを返す ブラウザは304のレスポンスが得られたらキャッシュをレスポンスのボディとしてユーザー に表示する
  9. Laravel門外漢の雑実装その2 擬似コード的な内容ですがやり たいことは伝わるのではないで しょうか。 実際にはこの辺のETag絡みの処 理は middleware に切り分けた ほうがいいと思います。 ここでは省略していますがこの

    ままだとviewのコードをいじっ てもキャッシュが更新されない ので、アプリケーションのバー ジョン情報などを設けておいて ETagに含めたほうがいいか も。
  10. max-age、Expires • Cache-Control: max-age=300 のように指定するとキャッシュのTTLを指 定できる。この例だとレスポンスが生成された時点から300秒間はキャッ シュを使用し、条件付きリクエストも送られなくなる。300秒経過後、再度 リクエストした場合には条件付きリクエストが送られる。 • Expires

    は相対的な秒数ではなくて、TTLが切れる時刻を絶対時間で指定で きる。Expires: Wed, 21 Oct 2015 07:28:00 GMT のように指定。 max-ageと同時に指定すると max-age が優先される。max-ageに対応して ない古いブラウザ向け。 • キャッシュのTTLを指定してやるとリアルタイムに更新が反映されなくなる が、条件付きリクエストの頻度を抑えることができる。
  11. Proxy, CDN • ここまででブラウザキャッシュの話をしてきましたが、これはいわゆる private キャッシュで、同じ人が2回目以降にアクセスしてきた時の話。 • つまり、初見のユーザーが大量に押し寄せてきた、みたいなケースには対応 できない。 •

    「商品一覧」は見る人によって表示が変わるわけではないので一度キャッ シュされた内容が広く共有されてほしい → sharedキャッシュが必要。 • そこでブラウザだけでなく Proxy や CDN にもキャッシュしてもらう。
  12. Proxy, CDN Proxy: いわゆるリバースプロキシ。Varnish, Squid, Nginx等。Webサーバーの 前でリクエストを処理してくれる。 CDN: Contents Delivery

    Network。ウェブコンテンツをインターネット経由で 配信するために最適化されたネットワークのこと。様々な機能があるが、Proxy 同様Webサーバーの前でキャッシュによるレスポンスを行ってくれる。
  13. Proxy/CDN Origin 1. ユーザーAが商品一覧ページ をリクエスト 2. Proxy/CDN はキャッシュがな いのでコンテンツをオリジンに リクエスト

    3. オリジンは Proxy/CDN にコ ンテンツをレスポンス 4. Proxy/CDN はオリジンからの レスポンスをキャッシュしたう えでユーザーにレスポンスす る。 5. ユーザーBが商品一覧ページ をリクエスト 6. Proxy/CDNはユーザーAのリ クエスト時にキャッシュしたコ ンテンツをBにレスポンス
  14. Cache-Control: private, public Cache-Control: private レスポンスがプライベートキャッシュ(ブラウザーのローカルキャッシュなど) にのみ保存できることを示す。これが付いてると Proxy や CDN

    にはキャッシュ されなくなる。 Cache-Control: public これがないと Proxy や CDN がキャッシュしてくれない・・・わけではない。リ クエストに Authorization ヘッダが付いていると普通そのレスポンスは shared キャッシュとして保存してはいけないのだが、それでもキャッシュさせたい、と いう場合に付ける。
  15. Cache-Control: private, public • Cache-Control: private/public は単にキャッシュの保存先を指定するだけで はなく、「通常キャッシュされないレスポンスでもキャッシュする」という 意味を持っていることに注意。 •

    例えば 403 のようなステータスコードでもキャッシュされてしまう可能性が ある(ブラウザや Proxy/CDN の実装によります) • CDN が public を付けないとキャッシュしない仕様だとか、リクエストに Authorization ヘッダが付いていてもキャッシュしたいとかでなければ public は付けないほうがいい
  16. まとめ • キャッシュは思ってるより身近なもの • 動的コンテンツでも工夫次第ではキャッシュできるよ • キャッシュと仲良くしてエコなアプリケーション開発をしよう 参考文献 田中 祥平

    『Web配信の技術―HTTPキャッシュ・リバースプロキシ・CDNを活用する』技術評論社 (2021/2/10) MDN Web Docks “Cache-Control - HTTP | MDN” https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cache-Control IETF “RFC 9110: HTTP Semantics” https://www.rfc-editor.org/rfc/rfc9110.html IETF “RFC 9111: HTTP Caching” https://www.rfc-editor.org/rfc/rfc9111.html