我正在使用Dragonfly为我的 Rails 应用程序提供处理后的图像。Dragonfly 依赖Rack::Cache来访问那些处理过的图像,这样Dragonfly 就不必一次又一次地处理这些图像,从而浪费 CPU 时间。
我的问题从这里开始:如果我是对的,通过 Rack::Cache 发送文件仍然占用 Rails 进程,那么查看 30 个图像的页面,即使这些图像的文件大小很小,也会很好地占用 Rails 进程迅速地。如果更多的访问者来查看该页面,那么他们将体验到非常缓慢的响应时间。如何通过 X-Sendfile 获取这些文件?
我在 中设置了以下内容production.rb
,但我知道这些是针对 Rails 的资产,而不是 Dragonfly 文件:
config.serve_static_assets = false
config.action_dispatch.x_sendfile_header = "X-Sendfile"
我知道 Rack::Cache 以某种方式支持 X-Sendfile (可能通过Rack::Sendfile),因为它会产生一个响应#to_path
. 但是,我不知道如何启用它。当我检查来自 Rack::Cache 的文件时,我没有看到任何 X-Sendfile 信息:
Date: Wed, 02 Nov 2011 11:38:28 GMT
Server: Apache/2.2.3 (CentOS)
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.9
Content-Disposition: filename="2.JPG"
Cache-Control: public, max-age=31536000
Etag: "3174d486e4df2e78a5ff9174cacbede5787d4660"
X-Content-Digest: c174408eda6e689998a40db0aef4cdd2aedb3b6c
Age: 28315
X-Rack-Cache: fresh
Content-Length: 22377
Status: 200
Content-Type: image/jpeg
我知道,根据网络上的帖子,我应该看到如下内容:
X-Sendfile: /path/to/file
最后我不知道我必须配置它的 Dragonfly 还是 Rack::Cache (或两者)。如何让 Dragonfly 和/或 Rack::Cache 通过 X-Sendfile 提供文件?
关于我的设置的信息:
- 导轨 3.1.1
- 乘客 3.0.9
- 中央操作系统
- 据我所知,已安装 Sendfile 模块。我已经在我的虚拟主机配置
XSendFile On
中XSendFilePath /path/to/app
指定了,并且 Apache 没有抱怨该指令XSendFile
不存在。
谢谢!
更新 2011 年 11 月 6 日
基于这个旧的更新,只要Rack::Sendfile
放在前面Rack::Cache
,就会使用X-Sendfile。我做到了,这就是我的中间件的样子。但是,这些文件仍然没有 X-Sendfile 标签。同样,我不知道这是否是确定 X-Sendfile 是否启用的可靠方法,所以我检查了乘客队列。当我访问一个页面时,队列似乎受到了很大的阻碍。
2011 年 11 月 7 日更新
看来这纯粹是 Rack::Cache 和 Rails 3.1 的问题。虽然 Rack::Cache 支持通过 Rack::Sendfile 使用 X-Sendfile (就像我上面提到的,Rack::Cache,当使用Disk EntityStore时,to_path
因为它返回的body 是 File 的子类,所以它响应了),Rails 3.1使用自己的存储解决方案。Rails 3.1 使用ActiveSupport::Cache::FileStore,如果您没有在production.rb
文件中指定任何内容,则默认设置。
FileStore 的问题在于它返回的主体是要向上游发送的响应的一部分,因为该主体不响应to_path
. 主体是ActiveSupport::Cache::Entry的一个实例。您可以在此处看到,当要求 FileStore 读取缓存文件时,它会通过File.open('/path/to/file') {|f| Marshal.load(f) }
返回 Entry 实例来读取它。最终被上游传递并返回给客户端的值是Entry#value。
我的问题
为了帮助我决定是否应该修补这个问题,或者让 Rails 使用 Rack::Cache 自己的磁盘存储,我有一些问题:
- Rails 3.1 没有使用 Rack::Cache 自己的存储解决方案的原因是什么?为什么 Rails 有自己的?
- 使用 Marshal 是否有原因?是否有理由应该发回数据字节流?
我比平时更深入,如果我理解正确,我会感到惊讶。我希望能找到答案!