(转)RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

传统的Web服务器在处理文件下载的时候,总是先读入文件内容到应用程序内存,然后再把内存当中的内容发送给客户端浏览器。这种方式在应付当今大负载网站,音频视频网站力不从心。sendfile是现代操作系统支持的一种高性能网络IO方式,操作系统内核的sendfile调用可以将文件内容直接推送到网卡的buffer当中,从而避免了Web服务器读写文件的开销,实现了“零拷贝”模式。

作为最流行的轻量级Web服务器的翘楚,lighttpd提供了良好的sendfile支持,JavaEye网站服务器使用的就是lighttpd。在Linux操作系统上面,只需要在lighttpd.conf配置文件如下配置,lighttpd就会使用sendfile方式处理静态资源的下载,效率非常高:

引用
server.network-backend = "linux-sendfile"



但是在某些情况下,我们却无法直接让lighttpd处理文件的下载,比方说JavaEye网站需要统计帖子附件的下载次数,博客相册的点击次数,比方说需要对下载的文件进行权限的控制,特别是对于一些多用户系统,你不能让用户上传的私密文件被其他用户随便下载到,例如JavaEye圈子的共享文件不能够对圈子外的用户开放下载。因此,文件下载目录千万不能放到public目录下,不能让用户直接通过浏览器的URL地址访问到。在这种情况下,文件下载必须由服务器端应用程序来处理。

在RoR应用当中,我们可以在controller中使用send_file方法来控制文件的下载。send_file方法将下载的文件以4KB为单位写到一个输出流去。如果我们使用mongrel应用服务器的话,mongrel会在内存当中创建一个StringIO对象,把整个下载文件完整的读入内存,然后再向客户端或者前端的Web服务器写出。如果我们使用fcgi来运行RoR的话,fcgi会直接把输出流的内容向前端的Web服务器写出。

毫无疑问,我们可以看到这种下载处理方式有很大的性能缺陷:

1、当使用mongrel的时候,如果下载文件很大,会导致mongrel内存暴涨!

mongrel创建一个StringIO对象缓存整个输出内容,我们假设用户下载的是一个100MB的文件,该用户又很喜欢用多线程下载工具,他开了10个线程并发下载,那么mongrel的内存占用会暴涨1GB以上。而且最可怕的是,即使当用户下载结束以后,mongrel的内存都不会迅速回落,而是一直保持如此高的内存占用。这个缺陷非常容易被别有用心的黑客利用,攻击网站。这也是JavaEye网站为什么始终不用mongrel的原因之一。


2、当使用fcgi的时候,如果前端Web服务器没有足够大buffer,会导致fcgi进程被挂住

fcgi自己不开output buffer,而是实时写出输出内容,如果前端Web服务器用的是lighttpd,那么你很幸运,lighttpd会照单全收,一个字节都不拉下;如果前端Web服务器用的是nginx/apache,那么你很不幸,nginx/apache默认只开8K的buffer,收不下的那就对不起了,您慢点嘞,fcgi进程就被挂住了,只要客户端浏览器下载不结束,fcgi进程就被一直占用。

3、即使使用lighttpd+fcgi,也会对服务器造成不小的性能开销

lighttpd+fcgi是最理想的Rails部署环境,JavaEye网站使用的就是lighttpd+fcgi。当ruby程序执行send_file开始下载的时候,fcgi会以4KB为单位读入文件内容,然后立刻写出到lighttpd去,而lighttpd照单全收。因此当下载文件被完整的通过fcgi被flush到lighttpd的内存里面去以后,即使你杀掉fcgi进程,都丝毫不会影响文件下载。

也许你会问,lighttpd都吃下来文件内容,内存会不会暴涨?会的,我们假设同样的用户场景,某用户启动10个线程下载100MB的文件,fcgi进程内存不会发生变化,但是lighttpd会暴涨1GB。但所幸的是lighttpd的内存管理的不错,一旦用户取消下载,或者下载完毕,lighttpd立刻释放掉1GB的内存。

但是无论怎么说,ruby还是需要完整的读取下载文件,而lighttpd也需要开辟足够大的内存,处理整个文件的下载过程,对服务器开销还是很大的。我们的问题是,能不能让带权限控制的文件下载像lighttpd下载静态资源文件那样快,开销那样小呢?答案就是X-sendfile!

使用X-sendfile方式,服务器端应用程序不需要读取下载文件了,只需要设置response的header信息就足够了,此外还要附加一个信息“X-LIGHTTPD-send-file”信息给lighttpd,告诉lighttpd,文件下载我就不管了,你自己看着办吧:

Ruby代码 复制代码  收藏代码
  1. response.headers['Content-Type'] = @attachment.content_type   
  2. response.headers['Content-Disposition'] = "attachment; filename=\"#{URI.encode(@attachment.filename)}\""    
  3. response.headers['Content-Length'] = @attachment.size   
  4. response.headers["X-LIGHTTPD-send-file"] = @attachment.public_filename   
  5. render :nothing => true  
response.headers['Content-Type'] = @attachment.content_type
response.headers['Content-Disposition'] = "attachment; filename=\"#{URI.encode(@attachment.filename)}\"" 
response.headers['Content-Length'] = @attachment.size
response.headers["X-LIGHTTPD-send-file"] = @attachment.public_filename
render :nothing => true



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支持,仅仅需要你在配置文件打开就可以了:

引用
"allow-x-send-file"="enable"



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部署方案的优劣。

web_share:通过Lighttpd分享文件,实现上传下载 web_share 通过Lighttpd分享文件,实现上传下载 为什么用Lighttpd? 因为它安装包小…… 为什么这么简陋? 因为我菜。欢迎提PR来帮助我改进。 这个项目意义何在? 帮助不同设备之间传输文件。举个例子:手机和电脑要传文件,没有数据线/数据线坏了/电脑上没有合适的驱动,怎么办?希望此项目可以快速实现您传文件的目标。 如何使用 首先得有 git clone $CLONE_URL 检查代码,并确认没有混入恶意代码 稍作修改(在代码树的根目录中): $EDITOR lighttpd.conf # 至少要修改var.server_root行与ssl相关行 $EDITOR auth.user # 设置用户名和密码 运行服务器(在代码的根目录中):lighttpd -f lighttpd.conf 服务器运行在localhost上,端口号见lighttpd.conf中server.p 立即下载

相关推荐

lighttpd完全学习

lighttpd完全学习,适合新手文档参考,ppt文件

RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

传统的Web服务器在处理文件下载的时候,总是先读入文件内容到应用程序内存,然后再把内存当中的内容发送给客户端浏览器。这种方式在应付当今大负载网站,音频视频网站力不从心。sendfile是现代操作系统支持的一种高性能网络IO方式,操作系统内核的sendfile调用可以将文件内容直接推送到网卡的buffer当中,从而避免了Web服务器读写文件的开销,实现了“零拷贝”模式。 作为最流行的轻量级We...

robbin的专栏 285

MMCV安装后报错‘from mmcv import Config’?别慌,这是MMCV 2.0的锅!快速降级回退MMCV 1.x全指南

本文详细解析了MMCV 2.0版本升级导致的‘from mmcv import Config’报错问题,提供了从诊断到降级回退MMCV 1.x的完整解决方案。通过pip和OpenMIM工具链的实操指南,帮助开发者快速解决版本冲突,确保项目稳定运行。

weixin_29102619的博客 263

lighttpd 之十二 网络请求服务响应流程

10.1 概述        熟悉UNIX/Linux网络编程的读者知道,在编写网络通信程序的时候离不开这几个系统调用:如socket()、bind()、listen()、connect()、accept()、write()/read()、close()等。作为Web服务器网络应用程序,Lighttpd当然也毫不例外地要调用这些系统函数来接受客户端请求,提供资源服务。在第8章里,我们跳过了监听描...

caofengtao1314的专栏 1万+

光耦继电器电路分析

光耦电路的分析笔记

MingYue_SSS的博客 6876

从IPv6到Tomcat:彻底解决127.0.0.1拒绝连接的完整指南

本文提供了从IPv6到Tomcat的全面指南,帮助开发者彻底解决127.0.0.1拒绝连接的问题。涵盖网络协议栈、服务配置、端口管理等多个层面的排查方法,特别针对Tomcat服务提供了专项解决方案,确保开发者能够快速定位并修复连接问题。

weixin_29207439的博客 471

下载配置lighttpd ,lighttpd.conf

1. 创建开发子目录 dev/,下载 Lighttpd 源代码并解压到其下,最新 Lighttpd 稳定版代码为 lighttpd-1.4.19: $ mkdir dev $ cd dev $ wget http://www.lighttpd.net/download/lighttpd-1.4.19.tar.bz2 $ tar xjf l

LYJ个人博客,记录技术、八卦、生活,分享各种心得,期待与朋友们一同进步 5868

点云欧式聚类快速了解

一种基于欧氏距离度量的聚类算法基于KD-Tree的近邻查询算法是加速欧式聚类算法的重要预处理方法KD-Tree是由二分搜索树演变而来的用于大规模高维度数据查找场景当中的索引结构,主要用于最近邻查找和近似最近邻查找。将整个空间划分为二叉树的形式,方便有效找到最近邻点云处理算法库PCL,是比较重要的,在后续会继续学习,然后发出更优质的文章。

xiaobaiwsc的博客 1722

安装lighttpd

  1.         安装编译环境   从 LINUX5.5 光盘中 server 目录下找到如下 rpm 包: 升级安装 rpm -Uvh --force --nodeps *rpm   2.         下载 lighttpd 从 http://lighttpd.net/downl...

tl_oni 289

WPF的基础设施:XAML基础语法

XAML是WPF的核心标记语言,采用XML语法实现界面与逻辑分离。其基础语法包括:1)控件声明方式(特性语法和属性元素语法);2)x:Name与Name的区别(适用范围和编译行为);3)注释规范与代码折叠技巧;4)实用特性如属性继承、附加属性等。文章还提供了常见错误排查方法,建议通过实践练习掌握XAML开发技巧。全文系统介绍了XAML的核心语法与应用场景,是WPF开发者的基础学习指南。

Hare的博客 1756

QGis二次开发 —— 5.2、基于qgis搭建离线地图服务并开发雷达扫描、无人机飞行跟踪等(附:源码及工程)

QGis二次开发 —— 5.2、基于qgis搭建离线地图服务并开发雷达扫描、无人机飞行跟踪等(附:源码及工程)

222

转:RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

http://www.iteye.com/topic/154538 传统的Web服务器在处理文件下载的时候,总是先读入文件内容到应用程序内存,然后再把内存当中的内容发送给客户端浏览器。这种方式在应付当今大负载网站,音频视频网站力不从心。sendfile是现代操作系统支持的一种高性能网络IO方式,操作系统内核的sendfile调用可以将文件内容直接推送到网卡的buffer当中,从

vah101的专栏 1277

【推荐100个unity插件】基于关节物理控制的自行车、电动车、摩托车模拟解决方案——Simple Bicycle Physics

摘要 "简易自行车物理"是Unity的自行车模拟资源包,支持Animation Rigging,实现基于关节物理的自行车控制。兼容所有平台和渲染管线,包含预制体、材质、脚本等资源。核心脚本Bicycle Controller管理自行车物理属性,支持自定义角色设置和移动端控制。安装后,用户可快速配置骑行场景,调整转向、速度、重心等参数,并支持地面贴合、兔跳等功能。适用于开发各类自行车模拟游戏和应用。 (字数:149)

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1366

Apache,Nginx,Lighttpd分别使用X-sendfile功能提升文件下载性能

关于mod_xsendfile https://tn123.org/mod_xsendfile/   Lighttpd中的X-sendfile RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能 使用X-sendfile方式,服务器端应用程序不需要读取下载文件了,只需要设置response的header信息就足够了,此外还要附加一个信息“X-

wang_kailiang的专栏 1105

Unity-Mirror网络框架-从入门到精通之MultipleMatches示例

Multiple Matches 示例主要讲述了如何在使用 Mirror 网路框架时管理多个游戏匹配。以及如何设置一个能够同时支持多个游戏会话的系统,使玩家能够加入他们所选择的比赛,而不是强制他们加入一个单一的匹配。

TxNet 964

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

JavaEye网站的RoR性能优化

JavaEye网站的RoR性能优化经验谈http://www.javaeye.com/topic/157731RoR部署方案深度剖析http://www.javaeye.com/topic/155542在Linux平台上安装和配置Ruby on Rails详解http://www.javaeye.com/topic/43228RoR网站如何利用lighttpd的X-sendfile功能提升...

weixin_30297281的博客 136

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

关于Ruby on Rails的几篇文章收集

RoR部署方案深度剖析http://www.javaeye.com/topic/155542RoR2.0的新特性:http://robbin.javaeye.com/blog/147397RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能 

维生素C.net 1315

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

多大的文件开始不用send_file,该怎么处理

今天看了下robin的文章http://www.iteye.com/topic/154538 ”RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能“ 我想问,多大的文件开始不用rails的send_file,而使用lighttpd的X-sendfile,内存不足。 比如一个相册图片1M,如果用send_file感觉是不是有点大了? 但是不用send_file直

xwnsy86276的专栏 694

Apache Nginx lighttpd HAProx Litespeed 缓冲原理解析fastcgi性能

<br />由于最近在忙于web server的开发,对于静态部分跟动态部分的交互一直迟迟未定,缓冲区大小也一直很头疼,看了下面的这篇文章觉得不错,我还是这样觉得,简单的就是最好的,但并不意味着所有处理都用一种方式,正如我在静态输出的socket buffer上面一样,我是根据请求内容的大小来决定缓冲区分配的,即使这样作在系统内部会形成一次内存拷贝(socket回去处理),但是相对于网络的延迟速度快多了,所以我觉得还是根据不同的内容和大小决定缓冲区大小,既不是lighttpd的照单全收,也不是nginx等的

zhangxinrun的专栏 944

Lighttpd入门教程

Lighttpd入门教程

qq_46017342的博客 8490

使用sendfile() 提高网络文件发送性能

我们平时通过网络发送文件时会用到的两个系统调用: read(file, tmp_buf, len); write(socket, tmp_buf, len); 调用过程示意图如下: 在用户空间调用 read() 读取文件时发生两次内存拷贝: DMA引擎将文件读取到内核的文件缓冲区 调用返回用户空间时将内核的文件缓冲区的数据复制到用户空间的缓冲区 接着调用 wr

zhaqiwen的专栏 1397
上一篇: (转)在 Linux 平台上安装和配置 Ruby on Rails 详解
下一篇: (转)RoR部署方案深度剖析
xinlanzero
博客等级 码龄25年 10粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值