HTTPキャッシュ


Diffこの記事は BOOK から派生したものであり、既存の公式ドキュメントとは異なります。この記事では、いくつかの場所でさらに詳しく説明します。したがって、公式との同期を強制することはありませんでした。

リッチ Web アプリケーションの本来の特性は、動的であることです。プログラムがどれほど効率的であっても、各リクエストには常に静的ファイルよりもはるかに大きなオーバーヘッドがかかります。

そして、多くの Web プログラムは大きな影響を受けていません。 symfony は非常に高速で、非常に負荷の高い作業を行っている場合を除き、サーバーに過度のストレスをかけることなく、すべてのリクエストがすぐに復元されます。

しかし、サイトは成長しており、過負荷が問題になる可能性があります。一般的なリクエストの処理は 1 回だけ行う必要があります。そして、それがまさにキャッシュ ロックの目的です。

巨人の肩に乗ったキャッシュ

プログラムのパフォーマンスを向上させる最も効果的な方法は、ページの出力全体をキャッシュし、出力全体を無視することです。その後のリクエスト。もちろん、非常に動的な Web サイトの場合、これが常に当てはまるとは限りません。この章では、Symfony のキャッシュ システムがどのように機能するのか、そしてそれが最適なソリューションである理由を学びます。

Symfony キャッシュ システムは、HTTP 仕様 で定義された HTTP キャッシュのシンプルさと強力に依存しているため、これとは異なります。 Symfony はキャッシュ手法を再発明するのではなく、Web 上の基本的な通信を定義する標準を重視しています。 「HTTP 検証」と「キャッシュされたモデルの有効期限」の基本をマスターすれば、すでに Symfony のキャッシュ システムをマスターできます。

Symfony キャッシュを学習するプロセスは 4 つのステップに分けることができます:

  1. ゲートウェイ キャッシュ (ゲートウェイ キャッシュ) またはリバース プロキシ (リバース プロキシ) )、これはプログラムの前にある別のレイヤーです。リバース プロキシは、プログラムから返される応答をキャッシュします。また、リクエストがプログラムに到達する前に、キャッシュされた応答でリクエストに応答することもできます。 symfony は独自のリバース プロキシを提供しますが、任意のリバース プロキシが機能します。

  2. HTTP キャッシュHTTP キャッシュ ヘッダーは、プログラムとクライアントの間でゲートウェイ キャッシュまたは他のキャッシュと通信するために使用されます。 Symfony は、キャッシュヘッダーと対話するための合理的なデフォルト設定と強力なインターフェイスを提供します。

  3. HTTP有効期限と検証 (有効期限と検証)、これら 2 つのモデルは、キャッシュされたコンテンツが fresh/fresh(キャッシュから再利用可能)、または stale/stale (プログラムによって再生成される必要がある)

  4. エッジ サイド インクルード (ESI) 、エッジサイドに含めることで、HTTP キャッシュをページの一部 (ネストされたフラグメントも) の独立したキャッシュに使用できるようになります。 ESI を利用すると、「ページ全体を 60 分間キャッシュし、サイドバーを 5 分間だけキャッシュする」こともできます。

HTTP キャッシュは Symfony に限定されたものではないため、関連記事が多数あります。 HTTP キャッシュに詳しくない場合は、Ryan Tomayko 著の Things Caches Do を読むことを強くお勧めします。もう 1 つの優れた詳細記事は、Mark Nottingham の キャッシュ チュートリアル です。

ゲートウェイ キャッシュの使用

HTTP キャッシュを使用する場合、cache はプログラムから完全に分離され、プログラムとリクエストを開始するサーバーの間に存在します。 .クライアント間で。

キャッシュのタスクは、クライアントのリクエストを受信し、それをプログラムに渡し、さらにクライアントにプッシュすることです。ここでのキャッシュは、プログラムとブラウザ間の「リク​​エストとレスポンス」通信プロセスにおける「仲介者」です。

時間が経つと、これらのキャッシュには「キャッシュ可能」とみなされるすべての応答が保存されます (HTTP キャッシュの概要 を参照)。同じリソースが再度リクエストされた場合、キャッシュはアプリケーションを完全に無視して、キャッシュされた応答をクライアントに送信します。

このタイプのキャッシュは HTTP ゲートウェイ キャッシュで、VarnishSquid、エージェント間の Symfony のリバース プロキシ モードなどのプログラムに存在します。

キャッシュ タイプ

ただし、ゲートウェイ キャッシュが唯一のキャッシュ タイプではありません。実際、プログラムによって送信された HTTP キャッシュ ヘッダーは、最大 3 つのキャッシュ方法によって解釈されると想定されています。

  • ブラウザ キャッシュ : 各ブラウザには独自のキャッシュがあります。ローカル キャッシュが組み込まれており、「戻る」をクリックしたとき、または画像やその他のアセットに使用されます。キャッシュされたリソースは他のユーザーが使用できないため、ブラウザー キャッシュはプライベート (プライベート) キャッシュです;

  • プロキシ キャッシュ : プロキシが参照します多くの人が 1 人をフォロー (使用) できるため、共有 (shared) キャッシュに保存されます。通常、アクセス遅延とネットワーク トラフィックを削減するために、大企業または ISP によって使用されます。

  • ゲートウェイ キャッシュ: プロキシと同様に、これも共有キャッシュですが、サーバー側にあります。 Web サイトのアップグレードを容易にし、信頼性とパフォーマンスを向上させるために、ネットワーク管理者によってよく使用されます。

ゲートウェイ キャッシュは、リバース プロキシ キャッシュ、サロゲート キャッシュ (プロキシ キャッシュ)、さらには HTTP アクセラレータと呼ばれることもあります。

#キャッシュされた応答に特定のユーザーのコンテンツ (アカウント情報など) が含まれる状況について議論する場合、プライベート (

private ) キャッシュと共有 (shared) キャッシュの重要性は日に日に増しています。

プログラムのすべての応答は、最初の 2 つのキャッシュ タイプの一方または両方を経験します。これらのキャッシュは (プログラムの) 制御の範囲外ですが、応答に設定された HTTP キャッシュ命令に従います。

Symfony リバース プロキシ

Symfony には、PHP で書かれたリバース プロキシ (ゲートウェイ キャッシュとも呼ばれます) が組み込まれています。 これは、Varnish のようなフル機能のリバース プロキシ キャッシュではありませんが、良いスタートとしては最適です。

プロキシを有効にするのは簡単です。Symfony プログラムはすべて、デフォルトのコア (

AppKernel) パックします。このキャッシュ コア はリバース プロキシです。 キャッシュをオンにするのは簡単です。フロント コントローラーのコードを変更するだけです。 app_dev.php に次の変更を加えて、

dev

環境のキャッシュを追加することもできます。

// web/app.phpuse Symfony\Component\HttpFoundation\Request;
// ...$kernel = new AppKernel('prod', false);$kernel->loadClassCache(); 
// add (or uncomment) this new line! / 添加下面新行!
// wrap the default AppKernel with the AppCache one
// 用AppCache打包默认的AppKernel$kernel = new AppCache($kernel); $request = Request::createFromGlobals(); $response = $kernel->handle($request);$response->send(); $kernel->terminate($request, $response);
上記のキャッシュ コアは、すぐにリバース A プロキシとして機能します。アプリケーションからの応答をキャッシュし、クライアントに返すことによって機能します。

framework.http_method_override
オプションを使用して
_method

パラメーターから HTTP メソッドを読み取る場合は、上記のリンクを参照して調整してください。それはあなたにとって必要な度合いです。

キャッシュ コアには特別な
getLog()
メソッドがあり、キャッシュ層で何が起こったかを示す文字列を返します。開発環境では、これを使用してキャッシュ戦略をデバッグまたは検証できます。

1
#
error_log($kernel->getLog());
#

AppCache オブジェクトには適切なデフォルト設定がありますが、getOptions() メソッドをオーバーライドすることにより、一連のオプションを設定するために、オブジェクトを微調整できます。

// app/AppCache.phpuse Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache; class AppCache extends HttpCache{
    protected function getOptions()
    {
        return array(
            'debug'                  => false,
            'default_ttl'            => 0,
            'private_headers'        => array('Authorization', 'Cookie'),
            'allow_reload'           => false,
            'allow_revalidate'       => false,
            'stale_while_revalidate' => 2,
            'stale_if_error'         => 60,
        );
    }}


getOptions() メソッドでオーバーライドされない限り、debub オプションは自動的にデバッグに設定されます。 「削除された AppKernel」の値。


主なオプションの一部を次に示します:

default_ttl

値は秒単位です。 、明示的な鮮度情報が応答で提供されない場合、キャッシュ エントリはどのくらいの期間新鮮であるとみなされるかを表します。この値は、Cache-Control または Expires ヘッダー (デフォルトは 0) を明示的に指定することでオーバーライドできます。


_headers

Cache-Control ディレクティブを渡す (デフォルトは AuthorizationCookie です) 現在の応答が publicprivate であるかを明示的に示す応答で「プライベート」キャッシュをトリガーします ステータス」 -

動作を制御します。

allow_reload

クライアントがリクエストに Cache-Control "no" を含めることができるかどうかを指定します-cache" ディレクティブを使用して、キャッシュのリロードを強制します。 RFC2616 に準拠するには、true に設定します (デフォルトは false

)。

allow_revalidate

クライアントがリクエストの最大値に Cache-Control に「」を含めることができるかどうかを指定します-age=0" を使用して再検証を強制します。 RFC2616 に準拠するには、true に設定します (デフォルトは false

)。

stale_while_revalidate

指定されたデフォルトの秒数 (応答の TTL 精度が秒であるため、間隔は秒単位です)、この間、キャッシュはバックグラウンドで応答を再検証していますが、すぐに古い応答を返す可能性があります (デフォルト値は 2)。この設定は HTTPCache によって変更できます。 Control 拡張 stale-while-revalidate

オーバーライド (RFC 5861 を参照)。

stale_if_error

キャッシュがサービスを提供するために応答できるデフォルトの秒数 (秒単位の間隔) を指定します (デフォルト)は 60)。この設定は、HTTPCache-Control 拡張機能の stale-if-error

によってオーバーライドできます (RFC 5861 を参照)。

debugtrue に設定されている場合、Symfony は応答に X-Symfony-Cache

ヘッダーを自動的に追加します。キャッシュのヒットとミスに関する有益な情報があります。

あるリバース プロキシから別のリバース プロキシへの切り替え

Web サイトを開発するとき、または Web サイトを共有ホスティングにデプロイするプロセス中に、「PHP コード以外は何も実行できない」インストールされています」 、Symfony のリバース プロキシは非常に便利なツールです。ただし、PHP で書かれているため、C で書かれたプロキシほど高速ではありません。このため、可能な限り運用サーバーでは Vanish または Squid を使用することを強くお勧めします。幸いなことに、プログラム内に変更するコードがないため、あるプロキシ サーバーから別のプロキシ サーバーへの切り替えは簡単かつ透過的です。 Symfony リバース プロキシは安心して使用でき、将来トラフィックが増加した場合はいつでも Varnish にアップグレードできます。
###

Symfony リバース プロキシのパフォーマンスは、プログラムの複雑さに依存しません。これは、プログラム カーネルは、リクエストを送信する必要がある場合にのみ起動されるためです。

応答を HTTP キャッシュにする

利用可能なキャッシュ層を利用するには、プログラムは次の情報と通信する必要があります。どの応答をキャッシュできるか。 2. キャッシュがいつ、どのように失効するかを決定するルール。

「HTTP」は、クライアントとサーバーが相互に通信するために使用する単なる言語 (単純なテキスト) であることに注意してください。 HTTP キャッシュはこの言語の一部であり、クライアントとサーバーがキャッシュに関する情報を交換できるようにします。

#HTTP は、応答用に次の 4 つのキャッシュ ヘッダーを指定します。

  • ##Cache-Control

  • 期限切れ

  • ETag

  • 最終更新日

最も重要かつ強力なヘッダーは、さまざまなキャッシュ情報の集合体である

Cache-Control ヘッダーです。

各ヘッダーについては、

HTTP の有効期限、検証、および無効化セクションで詳しく説明します。

Cache-Control ヘッダー

Cache-Controlヘッダーは特別であり、複数のヘッダーが含まれていますが、応答のキャッシュ可能性に関する多くの情報。各情報はカンマで区切られます:

Cache-Control: private, max-age=0, must-revalidate
 
Cache-Control: max-age=3600, must-revalidate

Symfony は、作成をより管理しやすくするために、

Cache-Control ヘッダーに抽象化レイヤーを提供します:

// ... use Symfony\Component\HttpFoundation\Response; $response = new Response();
// mark the response as either public or private 标记响应是公有还是私有$response->setPublic();$response->setPrivate();
// set the private or shared max age 设置私有或公有的最大周期$response->setMaxAge(600);$response->setSharedMaxAge(600); 
// set a custom Cache-Control directive 设置一个自定义Cache-Control命令$response->headers->addCacheControlDirective('must-revalidate', true)

コントローラーのさまざまなアクションにキャッシュ ヘッダーを設定したい場合は、

FOSHttpCacheBundle を参照してください。 URL パターン マッチングやその他のリクエスト属性に基づいてキャッシュ ヘッダーを定義する方法を提供します。

パブリック レスポンスとプライベート レスポンス

ゲートウェイ キャッシュでもプロキシ キャッシュでも、キャッシュ コンテンツはより多くのユーザーによって共有されるため、「共有」共有キャッシュとみなされます。 「ユーザー固有の」応答が誤って共有キャッシュに置かれた場合、後で複数の異なるユーザーに返される可能性があります。あなたのアカウント情報がキャッシュされ、その後アカウント ページをリクエストしたすべてのユーザーに送信されたらどうなるかを想像してみてください。

この状況に対処するには、各応答をパブリックまたはプライベートに設定する必要があります。

public

は応答を示します。パブリック キャッシュとプライベート キャッシュの両方としてキャッシュする必要があります。


private

応答情報の全部または一部が特定のユーザーのみに提供されるため、キャッシュが禁止されることを示します。パブリックにキャッシュされています。


Symfony は保守的に各応答をプライベートに設定します。共有キャッシュ (Symfony リバース プロキシなど) を利用するには、応答を明示的に public に設定する必要があります。

安全なメソッド

HTTP キャッシュは、「安全な」HTTP メソッド (GET や HEAD など) でのみ機能します。いわゆるセキュリティとは、リクエストに対するサービス (ロギング、キャッシュ情報の処理など) を提供するときに、サーバー上のプログラムの状態を決して変更できないことを意味します。これは、非常に説得力のある重要な 2 つの結論につながります。

  • GET または HEAD リクエストに応じてプログラムの状態を変更してはなりません。ゲートウェイ キャッシュを使用しない場合でも、プロキシ キャッシュの本質は、GET または HEAD リクエストが実際にサーバーにヒットする場合とヒットしない場合があるということです。

  • PUT リクエストは期待しないでください。 、キャッシュのための POST または DELETE メソッド。これらのメソッドは、アプリケーションの状態が変化した場合 (ブログ投稿の削除など) に使用することを目的としています。それらをキャッシュすると、特定のリクエストがプログラムにヒットしたり、プログラムを変更したりするのを防ぐことができます。

キャッシュ ルールとデフォルト設定

HTTP1.1 では、Cache-Control が明示的に設定されていない限り、デフォルトであらゆるコンテンツをキャッシュできます。 head を指定しました。実際には、リクエストに Cookie が含まれている場合、認可ヘッダーが含まれている場合、安全でないメソッド (PUT、POST、DELETE など) が使用されている場合、または応答にリダイレクト ステータス コードが含まれている場合、ほとんどのキャッシュは何も行いません。

開発者が応答ヘッダーに何も設定しない場合、Symfony は次のルールに従って、意味のある保守的な Cache-Header ヘッダーを自動的に設定します。

  • キャッシュ ヘッダーが定義されていない場合 (Cache-ControlExpiresETag または Last -修正済み )、Cache-Controlno-cache に設定されます。これは、応答がキャッシュされないことを意味します;

  • Cache-Control が空の場合 (ただし、別のキャッシュ ヘッダーが設定されている場合)、その値は private、must-revalidate;

    に設定されます。
  • しかし、少なくとも 1 つの Cache-Control ディレクティブが設定されており、public または private ディレクティブが明示的に追加されていない場合、Symfony はprivate ディレクティブを自動的に追加します (s-maxage が設定されている場合を除く)

HTTP の有効期限、検証、および無効化

HTTP プロトコルは 2 つのキャッシュ モデルを定義します。

  • 組み込みによる 有効期限モデル (有効期限モデル) の利用 キャッシュ コントロール ヘッダーや Expires ヘッダーは、応答を「新鮮」とみなす期間を直接指定できます。キャッシュは有効期限を認識しており、キャッシュされたバージョンが有効期限に達して「古く」なるまで、同じリクエストは発行されません。

  • ページが本当に動的である場合 (プレゼンテーション層が頻繁に変更される場合)、検証モデルの使用が非常に必要です。このモデルでは、キャッシュは応答を保存しますが、各要求ごとにサーバーに「質問」します。キャッシュされた応答はまだ有効ですか?プログラムは、独立した応答識別子 (つまり、Etag ヘッダー) および/またはタイムスタンプ (つまり、Last-Modified ヘッダー) を使用して、現在のページがキャッシュされてから変更されたかどうかを確認します。発生しています。

HTTP 仕様について理解する

HTTP 仕様は、クライアントがクライアントと通信できるようにする、シンプルだが強力な言語を定義します。サーバ。 Web 開発者は、HTTP 仕様に規定されているリクエスト/レスポンス モデルによってキャッシュの取り組みを管理します。残念ながら、HTTP プロトコルの実際のドキュメント RFC2616 は読みにくいです。

しかし、RFC 2616 を上書きするための HTTP Bis が進行中です。新しいバージョンの HTTP については説明しませんが、元の HTTP プロトコルをクリーンアップしたものです。ドキュメントの構成も改善され、HTTP プロトコルが 7 つの部分に分割され、HTTP キャッシュに関する各部分は 2 つの別個の章 (P4 - 条件付きリクエスト および P6 - キャッシュ: ブラウザ) に分かれています。および中間キャッシュ)。

Web 開発者として、弊社の公式 Symfony チームは、HTTP プロトコルについて読むことを 強く推奨します。非常に明確かつ強力であるため、作成されてから 10 年が経過した現在でも、HTTP 仕様は非常に貴重です。これらの契約書の見た目を軽視しないでください。内容は表紙よりも何十万倍も美しいものです。

Expiration (有効期限)

expiration モデルは、2 つのキャッシュ モデルのうち、より効率的で直接的なものであるため、可能な限り使用する必要があります。応答が有効期限によってキャッシュされると、キャッシュは応答を保存し、プログラムに影響を与えることなく有効期限が切れる直前に応答を返します。

有効期限モデルは、Expires または Cache-Control の 2 つのほぼ同一の HTTP ヘッダーのいずれかを使用して実装できます。

Expires ヘッダーを使用して有効期限を制御する

HTTP 仕様によると、「Expires ヘッダー フィールドには、応答は古いとみなされます。」ここの Expires ヘッダーは、Response メソッド setExpires() に設定できます。 DateTime インスタンスをパラメータとして使用します:

$date = new DateTime();
$date->modify('+600 seconds'); 
$response->setExpires($date);

応答の HTTP ヘッダー情報は次のようになります:

Expires: Thu, 01 Mar 2011 16:00:00 GMT

setExpires()このメソッドは、HTTP 仕様の要件であるため、日付は GMT タイム ゾーンに自動的に変換されます。

HTTP バージョン 1.1 より前では、オリジン サーバーは Date ヘッダーを送信する必要がなかったことに注意してください。したがって、キャッシュ (ブラウザなど) では Expires ヘッダーを評価するためにローカル クロックが必要となり、キャッシュ期間の計算が時間のずれに対して脆弱になります。もう 1 つの Expires ヘッダー制限は、HTTP プロトコルで説明されているように、「HTTP/1.1 は 1 年以上前の日付の Expires を送信してはなりません。」です。 Cache-Control ヘッダーを使用して有効期限を制御する

Expires

ヘッダーの制限のため、ほとんどの場合、Cache-Control# を使用する必要があります。代わりに ## ヘッダーを使用します。 Cache-Control ヘッダーはさまざまなキャッシュ ディレクティブに使用されることに注意してください。たとえば、max-ages-maxage などです。 1 つ目はすべてのキャッシュに使用され、2 つ目はキャッシュが共有される場合にのみ使用されます。

// Sets the number of seconds after which the response
// should no longer be considered fresh// 设置“响应过期”的秒数$response->setMaxAge(600);
 // Same as above but only for shared caches
// 同上,但仅用于共享缓存$response->setSharedMaxAge(600);
Cache-Control

ヘッダーは通常、次の形式になります (ただし、他の指示がある場合もあります):

##
1
Cache-Control: max-age=600, s-maxage=600

有効期限と検証 (有効期限と検証)

もちろん、同じ Response# に対して検証と有効期限を同時に使用することもできます。 ##。有効期限の利点が検証よりも大きいため、両方の長所を簡単に活用できます。つまり、有効期限と検証を組み合わせて使用​​すると、キャッシュされたコンテンツを提供するようにキャッシュに指示すると同時に、一定の間隔 (有効期限) で逆方向にチェックして、キャッシュされたコンテンツがまだ有効であることを確認することができます。

注釈を使用して有効期限と検証用の HTTP キャッシュ ヘッダーを定義することもできます。

FrameworkExtraBundle ドキュメントを参照してください。

その他の Response メソッド

Response クラスには、キャッシュを処理するための多くのメソッドが用意されています。特に役立つものをいくつか紹介します。

// Marks the Response stale 标记响应过期$response->expire(); 
// Force the response to return a proper 304 response with no content
// 强制响应返回一个没有内容的恰当的304响应$response->setNotModified();

さらに、ほとんどのキャッシュ関連の HTTP ヘッダーは、

setCache() メソッドを使用して個別に設定できます。

// Set cache settings in one call$response->setCache(array(
    'etag'          => $etag,
    'last_modified' => $date,
    'max_age'       => 10,
    's_maxage'      => 10,
    'public'        => true,
    // 'private'    => true,
    ));

概要


Symfony の設計思想は、業界で認められた標準である HTTP に従うことです。キャッシュ機能も例外ではありません。 Symfony のキャッシュ システムをマスターするということは、HTTP キャッシュ モデルに精通し、それを効率的に使用できることを意味します。言い換えれば、Symfony のドキュメントやルーチンに依存せずに、Varnish に代表される HTTP キャッシュとゲートウェイ キャッシュの世界を探索できます。