(转)RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能
传统的Web服务器在处理文件下载的时候,总是先读入文件内容到应用程序内存,然后再把内存当中的内容发送给客户端浏览器。这种方式在应付当今大负载网站,音频视频网站力不从心。sendfile是现代操作系统支持的一种高性能网络IO方式,操作系统内核的sendfile调用可以将文件内容直接推送到网卡的buffer当中,从而避免了Web服务器读写文件的开销,实现了“零拷贝”模式。
作为最流行的轻量级Web服务器的翘楚,lighttpd提供了良好的sendfile支持,JavaEye网站服务器使用的就是lighttpd。在Linux操作系统上面,只需要在lighttpd.conf配置文件如下配置,lighttpd就会使用sendfile方式处理静态资源的下载,效率非常高:
X-LIGHTTPD-send-file告诉lighttpd,去硬盘的哪个路径找要下载的文件,最后一行啥都不输出了,下载不用ruby来管了。
而lighttpd收到X-LIGHTTPD-send-file信息以后,就会找到硬盘该文件,以静态资源文件的下载方式处理,丝毫不消耗lighttpd的内存。还是以某用户启动10个线程下载100MB文件为例,10个fcgi进程发送了response信息就处理完毕了,而lighttpd知道下载的是硬盘的静态文件,会以sendfile方式下载,文件内容就会被操作系统内核直接送到网卡的buffer里面,既不消耗ruby进程,也不消耗lighttpd,皆大欢喜。
在lighttpd-1.4.18版本里面,fastcgi方式已经内置X-sendfile支持,仅仅需要你在配置文件打开就可以了:
JavaEye网站在使用了X-sendfile功能之后,lighttpd的内存占用有明显的下降。未使用X-sendfile之前,lighttpd有时候内存占用会到200MB以上(有用户多线程下载附件),在使用X-sendfile之后,lighttpd的内存占用还从未突破20MB。
最后要提醒大家几个问题:
1、lighttpd-1.4.x不认X-sendfile这个header,只认X-LIGHTTPD-send-file
按照lighttpd网站自己的文档,以及各种各样流行的X-sendfile文档,设置的header都是X-sendfile,但是经过我们n次失败的摸索,才发现原来必须使用X-LIGHTTPD-send-file,这一点请不要被文档迷惑,目前好像也只有我们提出这个解决办法,互联网上面尚未看到其他人提出过,看来我们又首开先河了。用RoR就是这点好,你动不动就得自己先去当尝螃蟹的那个人。
2、lighttpd-1.5.0版本的X-sendfile设置有所改变
lighttpd-1.5.0版本还未发布正式版本,据说1.5.0已经认识X-sendfile这个header了,这个大家有兴趣自己测试吧。
补充几句:
1、lighttpd-1.4.18仅支持fastcgi情况下的X-sendfile,而1.5.0版本则支持各种情况包括fastcgi, scgi, http proxy, ajp等协议下的X-sendfile
2、apache不支持X-sendfile,可以通过第三方mod添加支持,但据说不太好用
3、nginx有类似lighttpd的X-sendfile,叫做X-Accel-Redirect,但是使用的限制比较大,必须实现在nginx上面配置到某个目录下的文件才具备这样的功能,而不像lighttpd,任意目录文件不需要配置都可以支持,因而很受人批评。
当然,我还是推荐大家使用lighttpd+fcgi,这是性能最佳Rails方案,我会另外写文章剖析Rails部署方案的优劣。