ETagキャッシュによるポーリング

変更に対するポーリング(新しい変更があるかどうかを繰り返しサーバーに問い合わせること)は、GitLabインスタンスに高い負荷をもたらします。なぜなら、通常少なくともいくつかのSQLクエリを実行する必要があるからです。これは大規模なGitLabインスタンス(GitLab.comのような)のスケーリングを非常に難しくするので、ポーリングが必要でデータベースに負荷をかけるような新機能の追加は許可していません。

その代わりに、RedisでETagキャッシュを使ったポーリングメカニズムを使うべきです。

使い方

  1. ポーリングしたいエンドポイントのパスをGitlab::EtagCaching::Router に追加します。
  2. レスポンスのポーリング間隔ヘッダーをGitlab::PollingInterval.set_header で設定します。
  3. Gitlab::EtagCaching::Store を使って、エンドポイントのパスのキャッシュ無効化を実装します。リソースが変更されるたびに、このリソースに依存しているパスの ETag を無効にする必要があります。
  4. このメカニズムが動作することを確認してください:
    • リクエストはステータスコード 304 を返すはずです。
    • SQL クエリがログに記録されていません。log/development.log

どのように動作するか

キャッシュ・ミス

Cache miss

キャッシュ・ヒット

Cache hit

  1. リソースが変更されるたびにランダムな値を生成し、Redisに保存します。
  2. クライアントがリクエストを行うと、ETag レスポンスヘッダに Redis の値を設定します。
  3. クライアントはレスポンスをキャッシュし(クライアントサイド・キャッシング)、同じリソースに対するそれ以降のリクエストでIf-None-Match ヘッダとして ETag を送信します。
  4. If-None-Match ヘッダが Redis の現在の値と一致する場合、リソースが変更されていないことがわかるので、データベースにクエリすることなく、すぐに 304 レスポンスを送信することができます。クライアントのブラウザはキャッシュされたレスポンスを使用します。
  5. If-None-Match ヘッダが Redis の現在の値と一致しない場合は、リソースが変更されたため、新しいレスポンスを生成する必要があります。

ETag キャッシュを有効にしたいエンドポイントでは、クエリパラメータ (例えば?scope=all) を使用しないでください。ミドルウェアはリクエストパスのみを考慮し、クエリパラメータは無視します。すべてのパラメータをリクエストパスに含める必要があります。こうすることで、クエリパラメータの並び順の問題を回避し、 ルートマッチを簡単にすることができます。

詳細は