Webキャッシュは、データベースキャッシュ、サーバー側キャッシュ(プロキシサーバーキャッシュ、CDNキャッシュ)、ブラウザーキャッシュに大別できます。
ブラウザキャッシュには、HTTPキャッシュ、indexDB、cookie、localstorageなどの多くのコンテンツも含まれています。ここでは、HTTPキャッシング関連のコンテンツについてのみ説明します。
HTTPキャッシングについて詳しく学ぶ前に、いくつかの用語を明確にしましょう。
-
キャッシュヒット率:すべてのリクエストの数に対する、キャッシュからデータを取得するリクエストの数の比率。理想的な状態は、高いほど良いということです。
-
期限切れのコンテンツ:設定された有効時間後に「失効」としてマークされたコンテンツ。通常、期限切れのコンテンツを使用してクライアントの要求に応答することはできません。オリジンサーバーに新しいコンテンツを要求するか、キャッシュされたコンテンツの準備ができていることを確認する必要があります。
-
検証:キャッシュ内の期限切れのコンテンツがまだ有効かどうかを検証し、検証に合格した場合は有効期限を更新します。
-
無効化:無効化とは、キャッシュからコンテンツを削除することです。コンテンツが変更された場合は、無効なコンテンツを削除する必要があります。
ブラウザキャッシングは、主にHTTPプロトコルで定義されたキャッシングメカニズムです。たとえば、HTMLメタタグ
<META HTTP-EQUIV = "Pragma" CONTENT = "no-store">
意味は、ブラウザが現在のページをキャッシュしないようにすることです。ただし、プロキシサーバーはHTMLコンテンツを解析せず、HTTPヘッダー情報を使用してキャッシュを制御するために一般的に広く使用されています。
ブラウザのキャッシュ分類
ブラウザのキャッシュは、強力なキャッシュとネゴシエーションのキャッシュに分けられます。ブラウザがページをロードするための簡単なプロセスは次のとおりです。
-
ブラウザはまず、このリソースのhttpヘッダー情報に基づいて、強力なキャッシュにヒットしたかどうかを判断します。キャッシュに直接追加されたリソースにヒットした場合、リクエストはサーバーに送信されません。
-
強力なキャッシュが失われた場合、ブラウザはリソースの読み込み要求をサーバーに送信します。サーバーは、ブラウザのローカルキャッシュが無効かどうかを判断します。使用できる場合、サーバーはリソース情報を返さず、ブラウザーは引き続きキャッシュからリソースをロードします。
-
ネゴシエーションキャッシュが欠落している場合、サーバーは完全なリソースをブラウザーに返し、ブラウザーは新しいリソースをロードして、キャッシュを更新します。
強力なキャッシュ
強力なキャッシュがヒットすると、ブラウザはサーバーにリクエストを送信しません。Chromeの開発者ツールでは、httpの戻りコードが200であることがわかりますが、[サイズ]列に(キャッシュから)として表示されます。
強力なキャッシングは、http returnヘッダーのExpiresまたはCache-Controlフィールドを使用して、リソースのキャッシュ時間を示すことによって制御されます。
有効期限が切れます
リソースの有効期限を指定するために使用されるキャッシュの有効期限は、サーバー側の特定の時点です。つまり、Expires = max-age +リクエスト時間であり、Last-modifiedと組み合わせて使用する必要があります。ただし、前述したように、キャッシュ制御の優先度は高くなります。Expiresは、Webサーバーの応答メッセージのヘッダーフィールドです。http要求に応答するとき、ブラウザーは、再度要求することなく、有効期限が切れる前にブラウザーキャッシュからデータを直接フェッチできることをブラウザーに通知します。
このフィールドは、Expires:Thu、31 Dec 2037 23:59:59GMTなどの時刻を返します。この時間は、このリソースの有効期限を表します。つまり、2037年12月31日の23:59:59まで有効です。つまり、キャッシュにヒットします。この方法には明らかな欠点があります。有効期限は絶対時間であるため、クライアントの現地時間を変更すると、サーバーとクライアント間の時間偏差が大きくなり、キャッシュが混乱します。そこで、Cache-Controlが開発されました。
キャッシュ制御
Cache-Controlは、Cache-Control:3600などの相対時間です。これは、リソースの有効期間が3600秒であることを意味します。相対時間であり、クライアント時間と比較されるため、サーバーとクライアント間の時間偏差は問題になりません。
Cache-ControlとExpiresは、サーバー構成で同時に有効または有効にすることができます。Cache-Controlは、同時に有効にすると優先度が高くなります。
Cache-Controlは、主に次の値を持つ複数のフィールドで構成できます。
1. max-age は、キャッシュが有効であり、単位がsである時間の長さを指定します。たとえば、Cache-Control:max-age = 31536000を設定します。これは、キャッシュの有効期間が(31536000/24/60 * 60)日であることを意味します。リソースに初めてアクセスすると、サーバーはExpiresフィールドも返し、有効期限は次のようになります。一年後。
キャッシュが無効になっておらず、有効時間が経過していない場合、リソースに再度アクセスするとキャッシュがヒットし、サーバーにリソースを要求せず、ブラウザーのキャッシュから直接フェッチします。
2. s-maxageは max-ageと同じで、max-ageとExpiresをカバーしますが、共有キャッシュにのみ適用され、プライベートキャッシュでは無視されます。
3. Public は、応答が任意のオブジェクト(要求元のクライアント、プロキシサーバーなど)によってキャッシュできることを示します。
4. プライベート は、応答を1人のユーザー(オペレーティングシステムユーザー、ブラウザーユーザーなど)のみがキャッシュでき、非共有であり、プロキシサーバーがキャッシュできないことを示します。
5. no-cache は、応答をキャッシュしたすべてのユーザーに、キャッシュされたデータを使用する前に、バリデーターを含む要求をサーバーに送信するように強制します。文字通りキャッシュしていません。
6. No-store はキャッシュを禁止し、リクエストごとにサーバーからデータを再取得します。
7. Must-revalidateは、ページが古くなっている場合は、サーバーにアクセスして取得することを指定します。この命令は一般的に使用されないので、あまり説明しません。
ネゴシエーションキャッシュ
強力なキャッシュが失われた場合、ブラウザはサーバーにリクエストを送信します。サーバーは、httpヘッダー情報のLast-Modify / If-Modify-SinceまたはEtag / If-None-Matchに従って、ネゴシエーションキャッシュがヒットしたかどうかを判断します。ヒットした場合、httpリターンコードは304であり、ブラウザはキャッシュからリソースをロードします。
Last-Modify / If-Modify-Since
ブラウザが初めてリソースを要求すると、サーバーから返されるヘッダーにLast-Modifyが追加されます。Last-modifyは、リソースの最終変更時刻を識別する時刻です。たとえば、Last-Modify:Thu、31 Dec 2037 23:59 :59GMT。
ブラウザがリソースを再度要求すると、送信される要求ヘッダーには、キャッシュ前に返されるLast-ModifyであるIf-Modify-Sinceが含まれます。If-Modify-Sinceを受信した後、サーバーは、リソースの最終変更時刻に従って、キャッシュにヒットしたかどうかを判断します。
キャッシュにヒットした場合、http304が返され、リソースコンテンツは返されず、Last-Modifyは返されません。サーバー時間の比較により、クライアントとサーバー間の時間差は問題を引き起こしません。ただし、リソースが最終変更時刻までに変更されているかどうかを判断するのが非常に正確でない場合があります(リソースが変更された場合、最終変更時刻も同じになる可能性があります)。そのため、ETag / If-None-Matchが登場しました。
ETag / If-None-Match
Last-Modify / If-Modify-Sinceとは異なり、Etag / If-None-Matchはチェックコード(ETag:エンティティタグ)を返します。ETagは、各リソースが一意であることを保証でき、リソースの変更によりETagが変更されます*。ETag値の変更は、リソースステータスが変更されたことを示します。サーバーは、ブラウザーで送信されたIf-None-Match値に従って、キャッシュがヒットしたかどうかを判断します。
ETag拡張説明
ETagは、URLごとに一意の値を生成し、リソースが変更されるとETagが変更されることを期待しており、大きな期待を寄せています。不思議なEtagはどのように生成されますか?Apacheを例にとると、ETagの生成は次の要因に依存します
-
ファイルのiノード番号。このiノードは他のiノードではありません。これは、Linux / Unixがファイルを識別するために使用する番号です。はい、ファイル名はファイルの識別には使用されません。コマンド「ls-I」を使用して確認します。
-
ファイルの最終変更時刻
-
ファイルサイズ
Etagを生成する場合、これらの要素の1つ以上を使用し、衝突防止ハッシュ関数を使用して生成できます。したがって、理論的にはETagが繰り返されますが、確率が非常に小さいため無視できます。
既存のLast-ModifiedはどのようにしてEtagを生成できますか?
Last-Modifiedを使用するだけで、ローカルにキャッシュされたコピーが十分に新しいかどうかをブラウザに知らせることができると思うかもしれませんが、なぜEtag(エンティティID)が必要なのですか?HTTP1.1でのEtagの出現は、主に、Last-Modifiedでは解決が難しいいくつかの問題を解決することです。
1. Last-Modifiedでマークされた最後の変更は、第2レベルまでしか正確にできません。1秒以内に複数回変更されたファイルがある場合、ファイルの変更時間を正確にマークすることはできません。
2.一部のファイルが定期的に生成される場合、コンテンツは変更されないが、Last-Modifiedが変更され、ファイルがキャッシュを使用できなくなることがあります。
3.サーバーがファイルの変更時刻を正確に取得できない場合や、プロキシサーバーの時刻と一致しない場合などがあります。
Etagは、サーバーによって自動的に生成されるか、開発者によって生成されるサーバー側の対応するリソースの一意の識別子であり、キャッシュをより正確に制御できます。Last-ModifiedとETagは一緒に使用できます。サーバーは最初にETagを検証します。それらが一貫している場合は、Last-Modifiedを比較し続け、最後に304を返すかどうかを決定します。
ユーザーの行動とキャッシング
ブラウザのキャッシュ動作は、ユーザーの動作にも関連しています。!!
ユーザーアクション |
有効期限/キャッシュ制御 |
最終変更/ Etag |
アドレスバーに入力 |
効果的 |
効果的 |
ページリンクジャンプ |
効果的 |
効果的 |
新しい窓 |
効果的 |
効果的 |
前方後方 |
効果的 |
効果的 |
F5リフレッシュ |
無効 |
効果的 |
Ctrl + F5リフレッシュ |
無効 |
無効 |
総括する:
ブラウザの最初のリクエスト:
ブラウザが再度要求した場合: