2011-11-02 51 views
2

我正在使用Dragonfly为我的Rails应用程序处理已处理的图像。蜻蜓依靠Rack::Cache将来访问那些处理过的图片,这样Dragonfly won't have to process those images again再次浪费了CPU时间。Rails/Dragonfly/Apache - Rack :: Cache - 如何使用X-Sendfile?

我的问题从这里开始:如果我是正确的,通过Rack :: Cache发送文件仍然繁忙的Rails进程,然后查看一个30页的图像,即使这些图像有一个小文件大小的页面将捆绑Rails处理非常快。如果有更多的访问者来看这个页面,那么他们的响应时间会非常缓慢。我如何通过X-Sendfile获取这些文件?

我已经设置在production.rb以下,但我知道这些都是从Rails的资产,而不是蜻蜓文件:

config.serve_static_assets = false 
config.action_dispatch.x_sendfile_header = "X-Sendfile" 

我知道这架::缓存以某种方式支持X-SENDFILE(可能通过Rack::Sendfile),因为它produces a body that responds to #to_path。但是,我不知道如何启用此功能。当我检查来自机架::缓存文件,我看不到任何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 

我知道,基于posts around the net,那我应该看到:

X-Sendfile: /path/to/file 

最后我不知道它的蜻蜓或Rack :: Cache(或两者),我必须配置。 如何通过X-Sendfile获得Dragonfly和/或Rack :: Cache服务文件?

信息关于我的设置:

  • 的Rails 3.1.1
  • 客运3.0.9
  • CentOS的
  • SENDFILE模块安装,据我所知。我在我的虚拟主机配置中指定了XSendFile OnXSendFilePath /path/to/app,并且Apache不抱怨指令XSendFile不存在。

谢谢!

UPDATE 2011年11月6日

基于this old update,只要Rack::Sendfile被放置在的Rack::Cache前面,则X-SENDFILE将被使用。我做到了,这是如何my middleware looks like。该文件,但是,still don't have the X-Sendfile tag。再一次,我不知道这是确定是否启用X-Sendfile的确定方法,因此我检查了Passenger队列。看来,当我访问一个页面时,队列大大受阻。

UPDATE 2011年11月7日

看来这纯粹是一个机架::缓存和Rails 3.1的问题。虽然Rack :: Cache支持通过Rack :: Sendfile使用X-Sendfile(就像我上面提到的,Rack :: Cache,自body it returns is a subclass of File以来使用Disk EntityStore以来的响应_ to_path),Rails 3.1使用它自己的存储解决方案。 Rails 3。1使用ActiveSupport::Cache::FileStore,如果您未在production.rb文件中指定任何内容,则默认设置此项。

FileStore的问题在于它返回的主体是要向上游发送的响应的一部分,因为该主体不响应to_path。身体是ActiveSupport::Cache::Entry的一个实例。您可以看到here,当FileStore被要求读取一个缓存文件时,它通过File.open('/path/to/file') {|f| Marshal.load(f) }读取它,它返回Entry的一个实例。最终通过上游并返回给客户端的值是Entry#value

我的问题

为了帮助我决定我是否应该修补这个,还是让Rails的使用机架::缓存自己的磁盘店不是,我有一些问题:

  1. 有什么原因Rack :: Cache自己的存储解决方案不适用于Rails 3.1?为什么Rails有它自己的?
  2. 是否有理由使用元帅?是否有理由将数据的字节流反向传回?

我深入到了比平时更深的地步,如果我正确地理解了事情,我会感到惊讶。我希望能找到答案!

+0

我问过周围,发送电子邮件到Rails用户组,但没有找到答案。是的,Varnish在开始时听起来像是过度杀伤性的,但为了让X-Sendfile能够正常工作,我需要进行所有更改,安装Varnish会更简单。 –

回答

1

作为Varnish的替代品,您可以使用Apache的mod_disk_cache。因为您已经在运行Apache,所以设置起来会更少。

1

我最终得到这个工作,虽然与nginx &独角兽,而不是Apache &乘客。

正如您在your Github issue中指出的那样,您可以将Rack :: Cache切换回使用其标准文件:/ store而不是rails:/ store,这将允许响应响应to_path

config.action_dispatch.rack_cache = { 
    :verbose  => true, 
    :metastore => URI.encode("file:/PATH/TO/CACHE/STORE"), 
    :entitystore => URI.encode("file:/PATH/TO/CACHE/STORE") 
} 

蜻蜓做到这一点的发展,如果你喜欢,你仍然可以做到这一点在生产。这样做需要注意的是,如果您使用任何使用Rack :: Cache的Rails缓存功能,缓存条目将存储在该存储中而不是标准的Rails中,因此如果您需要手动清除任何这些条目。

然后您还需要确保使用config.action_dispatch.x_sendfile_header参数在Rack的前面插入Rack :: Sendfile中间件。没有config参数,Rack :: Sendfile不会添加标题。

config.middleware.insert 0, Rack::Sendfile, config.action_dispatch.x_sendfile_header 

My Gist在production.rb和我的nginx模板中显示了我的相关行。应该很容易适应与Apache X-Sendfile模块一起工作。

还有一两件事要注意,如果你正在测试这一点,就是如果你只通过卷曲发送HEAD请求例如,你不会得到相关的X-SENDFILE头中的响应,机架::缓存实际上不会发送主体的头部请求,所以Rack :: Sendfile没有什么可以拨打to_path