【问题标题】:Rails Conditional Get not behaving properly on HerokuRails Conditional Get 在 Heroku 上的行为不正常
【发布时间】:2012-08-04 01:26:08
【问题描述】:

我有一个 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 在再次轮询之前只是休眠一段时间。

谢谢

【问题讨论】:

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


    【解决方案1】:

    问题的根源在于 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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 2020-09-21
      • 2011-07-14
      • 1970-01-01
      • 2013-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多