我有一个 Rails 3.2 应用程序,其中客户端轮询服务器中的资源以获取更新。此资源不是资产,而是动态内容。
我选择的实施策略是通过fresh_when指令的条件获取:
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 在再次轮询之前只是休眠一段时间。
谢谢