Rails条件在Heroku上运行不正常

时间:2012-08-04 01:26:08

标签: ruby-on-rails-3 http heroku http-etag

我有一个Rails 3.2应用程序,客户端轮询服务器中的资源以进行更新。此资源不是资产,而是动态内容。

我选择的实施策略是Conditional Get,通过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 架::缓存)

我不想要那些冗余响应的原因是因为它使用不需要的对象刷新来轰炸客户端应用程序,从而导致最终用户遭受严重的性能损失。当只从服务器返回302标头时,客户端javascript只会在再次轮询之前休眠一段时间。

由于

1 个答案:

答案 0 :(得分:0)

问题的根源在于API滥用。这一行:

fresh_when(etag: @etag, public: false)

在开发过程中表现如预期,但不在生产中。我认为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%确定缺少这个标题会在他们的堆栈中以某种方式弄乱请求/响应路径(假设他们在你的dyno前面有其他服务器,如Varnish和Nginx)