安徽新华电脑专修学院_安徽电脑培训_安徽电脑培训学校_合肥电脑培训

當(dāng)前位置:首頁 > 網(wǎng)站舊欄目 > 學(xué)習(xí)園地 > 設(shè)計(jì)軟件教程 > 利用lighttpd的X-sendfile提升Rails的下載性能

利用lighttpd的X-sendfile提升Rails的下載性能
2010-01-14 23:31:33  作者:  來源:
傳統(tǒng)的Web服務(wù)器在處理文件下載的時候,總是先讀入文件內(nèi)容到應(yīng)用程序內(nèi)存,然后再把內(nèi)存當(dāng)中的內(nèi)容發(fā)送給客戶端瀏覽器。這種方式在應(yīng)付當(dāng)今大負(fù)載網(wǎng)站,音頻視頻網(wǎng)站力不從心。sendfile是現(xiàn)代操作系統(tǒng)支持的一種高性能網(wǎng)絡(luò)IO方式,操作系統(tǒng)內(nèi)核的sendfile調(diào)用可以將文件內(nèi)容直接推送到網(wǎng)卡的buffer當(dāng)中,從而避免了Web服務(wù)器讀寫文件的開銷,實(shí)現(xiàn)了“零拷貝”模式。

作為最流行的輕量級Web服務(wù)器的翹楚,lighttpd提供了良好的sendfile支持,JavaEye網(wǎng)站服務(wù)器使用的就是lighttpd。在Linux操作系統(tǒng)上面,只需要在lighttpd.conf配置文件如下配置,lighttpd就會使用sendfile方式處理靜態(tài)資源的下載,效率非常高:

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


但是在某些情況下,我們卻無法直接讓lighttpd處理文件的下載,比方說JavaEye網(wǎng)站需要統(tǒng)計(jì)帖子附件的下載次數(shù),博客相冊的點(diǎn)擊次數(shù),比方說需要對下載的文件進(jìn)行權(quán)限的控制,特別是對于一些多用戶系統(tǒng),你不能讓用戶上傳的私密文件被其他用戶隨便下載到,例如JavaEye圈子的共享文件不能夠?qū)θψ油獾挠脩糸_放下載。因此,文件下載目錄千萬不能放到public目錄下,不能讓用戶直接通過瀏覽器的URL地址訪問到。在這種情況下,文件下載必須由服務(wù)器端應(yīng)用程序來處理。

在RoR應(yīng)用當(dāng)中,我們可以在controller中使用send_file方法來控制文件的下載。send_file方法將下載的文件以4KB為單位寫到一個輸出流去。如果我們使用mongrel應(yīng)用服務(wù)器的話,mongrel會在內(nèi)存當(dāng)中創(chuàng)建一個StringIO對象,把整個下載文件完整的讀入內(nèi)存,然后再向客戶端或者前端的Web服務(wù)器寫出。如果我們使用fcgi來運(yùn)行RoR的話,fcgi會直接把輸出流的內(nèi)容向前端的Web服務(wù)器寫出。

毫無疑問,我們可以看到這種下載處理方式有很大的性能缺陷:

1、當(dāng)使用mongrel的時候,如果下載文件很大,會導(dǎo)致mongrel內(nèi)存暴漲!

mongrel創(chuàng)建一個StringIO對象緩存整個輸出內(nèi)容,我們假設(shè)用戶下載的是一個100MB的文件,該用戶又很喜歡用多線程下載工具,他開了10個線程并發(fā)下載,那么mongrel的內(nèi)存占用會暴漲1GB以上。而且最可怕的是,即使當(dāng)用戶下載結(jié)束以后,mongrel的內(nèi)存都不會迅速回落,而是一直保持如此高的內(nèi)存占用。這個缺陷非常容易被別有用心的黑客利用,攻擊網(wǎng)站。這也是JavaEye網(wǎng)站為什么始終不用mongrel的原因之一。


2、當(dāng)使用fcgi的時候,如果前端Web服務(wù)器沒有足夠大buffer,會導(dǎo)致fcgi進(jìn)程被掛住

fcgi自己不開output buffer,而是實(shí)時寫出輸出內(nèi)容,如果前端Web服務(wù)器用的是lighttpd,那么你很幸運(yùn),lighttpd會照單全收,一個字節(jié)都不拉下;如果前端Web服務(wù)器用的是nginx/apache,那么你很不幸,nginx/apache默認(rèn)只開8K的buffer,收不下的那就對不起了,您慢點(diǎn)嘞,fcgi進(jìn)程就被掛住了,只要客戶端瀏覽器下載不結(jié)束,fcgi進(jìn)程就被一直占用。

3、即使使用lighttpd+fcgi,也會對服務(wù)器造成不小的性能開銷

lighttpd+fcgi是最理想的Rails部署環(huán)境,JavaEye網(wǎng)站使用的就是lighttpd+fcgi。當(dāng)ruby程序執(zhí)行send_file開始下載的時候,fcgi會以4KB為單位讀入文件內(nèi)容,然后立刻寫出到lighttpd去,而lighttpd照單全收。因此當(dāng)下載文件被完整的通過fcgi被flush到lighttpd的內(nèi)存里面去以后,即使你殺掉fcgi進(jìn)程,都絲毫不會影響文件下載。

也許你會問,lighttpd都吃下來文件內(nèi)容,內(nèi)存會不會暴漲?會的,我們假設(shè)同樣的用戶場景,某用戶啟動10個線程下載100MB的文件,fcgi進(jìn)程內(nèi)存不會發(fā)生變化,但是lighttpd會暴漲1GB。但所幸的是lighttpd的內(nèi)存管理的不錯,一旦用戶取消下載,或者下載完畢,lighttpd立刻釋放掉1GB的內(nèi)存。

但是無論怎么說,ruby還是需要完整的讀取下載文件,而lighttpd也需要開辟足夠大的內(nèi)存,處理整個文件的下載過程,對服務(wù)器開銷還是很大的。我們的問題是,能不能讓帶權(quán)限控制的文件下載像lighttpd下載靜態(tài)資源文件那樣快,開銷那樣小呢?答案就是X-sendfile!

使用X-sendfile方式,服務(wù)器端應(yīng)用程序不需要讀取下載文件了,只需要設(shè)置response的header信息就足夠了,此外還要附加一個信息“X-LIGHTTPD-send-file”信息給lighttpd,告訴lighttpd,文件下載我就不管了,你自己看著辦吧:

Ruby代碼 復(fù)制代碼
  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  


X-LIGHTTPD-send-file告訴lighttpd,去硬盤的哪個路徑找要下載的文件,最后一行啥都不輸出了,下載不用ruby來管了。

而lighttpd收到X-LIGHTTPD-send-file信息以后,就會找到硬盤該文件,以靜態(tài)資源文件的下載方式處理,絲毫不消耗lighttpd的內(nèi)存。還是以某用戶啟動10個線程下載100MB文件為例,10個fcgi進(jìn)程發(fā)送了response信息就處理完畢了,而lighttpd知道下載的是硬盤的靜態(tài)文件,會以sendfile方式下載,文件內(nèi)容就會被操作系統(tǒng)內(nèi)核直接送到網(wǎng)卡的buffer里面,既不消耗ruby進(jìn)程,也不消耗lighttpd,皆大歡喜。

在lighttpd-1.4.18版本里面,fastcgi方式已經(jīng)內(nèi)置X-sendfile支持,僅僅需要你在配置文件打開就可以了:

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


JavaEye網(wǎng)站在使用了X-sendfile功能之后,lighttpd的內(nèi)存占用有明顯的下降。未使用X-sendfile之前,lighttpd有時候內(nèi)存占用會到200MB以上(有用戶多線程下載附件),在使用X-sendfile之后,lighttpd的內(nèi)存占用還從未突破20MB。

最后要提醒大家?guī)讉問題:

1、lighttpd-1.4.x不認(rèn)X-sendfile這個header,只認(rèn)X-LIGHTTPD-send-file

按照lighttpd網(wǎng)站自己的文檔,以及各種各樣流行的X-sendfile文檔,設(shè)置的header都是X-sendfile,但是經(jīng)過我們n次失敗的摸索,才發(fā)現(xiàn)原來必須使用X-LIGHTTPD-send-file,這一點(diǎn)請不要被文檔迷惑,目前好像也只有我們提出這個解決辦法,互聯(lián)網(wǎng)上面尚未看到其他人提出過,看來我們又首開先河了。用RoR就是這點(diǎn)好,你動不動就得自己先去當(dāng)嘗螃蟹的那個人。

2、lighttpd-1.5.0版本的X-sendfile設(shè)置有所改變

lighttpd-1.5.0版本還未發(fā)布正式版本,據(jù)說1.5.0已經(jīng)認(rèn)識X-sendfile這個header了,這個大家有興趣自己測試吧。
安徽新華電腦學(xué)校專業(yè)職業(yè)規(guī)劃師為你提供更多幫助【在線咨詢
主站蜘蛛池模板: 铸铁型材_灰铁棒_球铁棒_圆铁棒生产厂家★河北起昌精密装备制造有限公司 | 吉林省创智汇成包装有限公司,长春高档礼盒,长春包装盒厂家,长春精品包装盒 | 西安泰富西玛电机有限公司总部-电机-高压电机-西玛电机-西安西玛电机-泰富西玛电机-西安电机厂-西玛电机销售 | 浙江创洁卫生消杀有限公司-浙江杀虫公司,温州消杀公司,温州灭鼠公司,灭蟑螂,灭蚊蝇,灭跳蚤,灭书虱,灭臭虫,灭螨虫,白蚁防治,房间消毒除味等专业服务 | 上海新航道学校官网_20年专注雅思_托福_SAT_ACT等出国语言培训机构. | 石家庄LED显示屏|石家庄显示屏|河北显示屏升级改造|石家庄科航光电科技有限公司_石家庄科航光电科技有限公司 | 手板机箱_亚克力机箱_医疗机箱_美容机箱_医疗设备外壳厂家_鸿堪医疗器械有限公司 | 青岛除甲醛公司|青岛甲醛治理|青岛除甲醛|甲醛检测|光触媒除甲醛|装修除味除甲醛|新房除甲醛|青岛室内环境污染检测治理|青岛闪洁环保科技有限公司官网 | 河南新飞飞鸿实业有限公司| 上海鑫鹏塑料制品有限公司| 危废处理_危废处置_危废处理公司-江苏绿瑞特环境科技股份有限公司 | 塑木地板-木塑地板厂家「云南昆明楚雄曲靖玉溪塑木地板」云南云冶中信塑木新型材料有限公司 | 粮食烘干机|玉米烘干机|稻谷烘干机|小麦烘干机|大型连续烘干塔|500吨连续烘干塔|钢板仓|-郑州新光矿山机械制造有限公司 | 小地磅,钢瓶秤,叉车称,轮椅秤,倒桶秤,畜牧秤,轴重仪,称重模块——上海实干实业有限公司-网站首页 | 仪器校准_校验_计量检测_校正_检定严选博罗第三方法定计量所 | 破碎机设备-锤式颚式反击式圆锥移动冲击式破碎机厂家-成都大宏立机器公司 | 九江市新双龙广告装饰有限公司| 文学素材,好词好句,正能量句子,百科知识-素文网 | 室内去除甲醛检测治理十大品牌_去除甲醛公司加盟-优吸环保科技有限公司集团总部官网 | 山东长青石油液压机械有限公司-致力于石油机械设备的研发制造,提供定制服务 | 山东德曼医疗设备集团有限公司 | 河北省金融租赁有限公司官网| 网站建设|营销型网站|独立站搭建|外贸网站建设|wordpress独立站|小程序开发-?无双建站? | 津南人才网_津南招聘网_求职找工作平台 | 橡胶粉碎机_轮胎粉碎机_橡胶切条机_橡胶粉碎机价格_河南鑫世昌机械制造有限公司 | 灭菌洗箱机_周转箱清洗机_隧道式洗箱机 - 环速科技有限公司 | 印刷公司,北京印刷厂,宣传画册手册印刷厂-和智印彩页设计 | 沥青灌缝胶-路面贴缝带-灌缝胶厂家-山东晟辉工程材料有限公司 | 汽车漆品牌|家具漆代理|涂料加盟厂家|家具漆|汽车漆-邦派漆官网 汽车漆|汽车油漆|工业油漆涂料|汽车漆加盟-佛山市科涂涂料有限公司 | 兰州环氧地坪,兰州防火涂料-甘肃皓天环氧地坪工程| 网站建设|营销型网站|独立站搭建|外贸网站建设|wordpress独立站|小程序开发-?无双建站? | 体育馆木地板厂家_篮球木地板价格_舞台木地板品牌-欧氏地板 | 上海鑫迪机械有限公司 上海科蜀智能机械有限公司 | 中捷摇臂钻,数控钻床,沈阳中捷设备机床厂官网_沈阳中捷数控摇臂钻床厂 | 洒水车_水车_洒水车价格_喷水车_绿化喷洒车_绿化洒水车- 程力专用汽车股份有限公司 | 银泰洁净--净化工程总承包,20年精耕细作,专为净化而来_银泰洁净--净化工程总承包,20年精耕细作,专为净化而来 | 粮食烘干机|玉米烘干机|稻谷烘干机|小麦烘干机|大型连续烘干塔|500吨连续烘干塔|钢板仓|-郑州新光矿山机械制造有限公司 | 天力普电力科技有限公司| 水处理设备厂家_纯净水设备_超纯水设备价格找西安瑞泉水处理 | 中国国际石油石化技术装备展览会|振威展览 | 喷雾式干燥机-真空桨叶干燥机-桨叶干燥器-常州力马干燥科技有限公司 |