0

クライアント側が更新のためにサーバー内のリソースをポーリングする Rails 3.2 アプリケーションがあります。このリソースはアセットではなく、動的コンテンツです。

私が選択した実装戦略は、fresh_when ディレクティブによる条件付き Getです。

fresh_when(:etag => @etag, :public => false ) #it's a private resource, requires auth etc

そのため、リソースがまだ新しい場合 (リクエストの 'If-Not-Modified' ヘッダーがリソースの現在の ETag と等しい)、サーバーは 304 ヘッダーのみを返します。

Started GET "/news/4fe13e74aa5e7d3d70000001"
Processing by NewsController#show as JSON
Parameters: {"id"=>"4fe13e74aa5e7d3d70000001"}
Completed 304 Not Modified

リソースが最新でなくなると、ステータス 200 になり、応答本文にリソースの最新バージョンが含まれます。

Started GET "/news/4fe13e74aa5e7d3d70000001"
Processing by NewsController#show as JSON
Parameters: {"id"=>"4fe13e74aa5e7d3d70000001"}
Rendered news/show.json.rabl (8.1ms)
Completed 200 OK in 14ms

開発環境では、これは完全に機能します。問題は本番環境 (Heroku Cedar Stack) にあります。このシナリオでは、応答は常に200 で、本文に完全なオブジェクト表現があります。

2012-08-03T21:44:33+00:00 heroku[router]: GET blah.com/news/4fa43b428b91cd0001000002 dyno=web.1 queue=0 wait=0ms service=22ms status=200 bytes=2105

2012-08-03T21:44:33+00:00 app[web.1]: Started GET "/news/4fa43b428b91cd0001000002"
2012-08-03T21:44:33+00:00 app[web.1]: cache: [GET /news/4fa43b428b91cd0001000002] miss

2012-08-03T21:44:33+00:00 heroku[nginx]: 187.38.19.138 - - [03/Aug/2012:21:44:33 +0000] "GET /news/4fa43b428b91cd0001000002 HTTP/1.1" 200 665 "http://www.bla.com/news/4fa43b428b91cd0001000002" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.57 Safari/537.1" 

見た目からすると、このリクエストは Rails コントローラー (鮮度が実際に評価される場所) に到達していませんが、heroku のルーターとキャッシュ層を通過しています。

私がこれまでに試したこと:

  • 両方の環境で、Rails (3.2.1) と Thin (1.3.1) のバージョンを再確認しました。
  • 「config.action_controller.perform_caching = false」の設定
  • Rack::Cache ミドルウェアの削除 (config.middleware.delete Rack::Cache)

これらの冗長な応答が不要な理由は、クライアント側のアプリに不要なオブジェクトの更新を爆撃し、エンド ユーザーのパフォーマンスに深刻な打撃を与えるためです。サーバーから 302 ヘッダーのみが返された場合、クライアント側の JavaScript は、再度ポーリングする前にしばらくスリープします。

ありがとう

4

1 に答える 1

0

問題の根本は、API の誤用にあります。この行:

fresh_when(etag: @etag, public: false)

開発では期待どおりに動作しますが、本番環境では動作しません。この種の条件付き get プロシージャには Etag/If-Not-Modified ヘッダーの交換で十分だと思ったので、「Last-Modified」ヘッダーを追加することは気にしませんでした。

HTTP 1.1 RFCを読んだ後、「HTTP/1.1 サーバーは、可能な限り Last-Modified を送信する必要があります。」私はそれを試してみることにしました:

fresh_when(etag: @etag, public: false, last_modified: @news.updated_at)

そして、Herokuでうまくいきました!このヘッダーがないために、スタックでリクエスト/レスポンスパスが何らかの形で台無しになっていることは 99% 確信しています (Varnish や Nginx などの dyno の前に他のサーバーがある場合)。

于 2012-08-08T04:23:34.933 に答える