以前我写过一篇关于nginx sendfile的文章,讲的是sendfile零拷贝理论方面,这次主要是讲实现的细节。 http://xiaorui.cc/?p=1673

    sendfile的流程示意图 :

        

     nginx有个sendfile参数,我想大家一般都是开启的。 简单说sendfile可以高效传输静态文件,尤其针对静态文件下载的逻辑。 sendfile的好处主要是两点,  普通的sendall流程是,kernel buffer — > user buffer — > kernel socket buffer –> 协议栈,对于sendfile来说,他的流程是kernel buffer –> kernel socket buffer –> 协议栈.  很明显减少copy的次数,另外这也减少了上线文切换的次数。

该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。http://xiaorui.cc/?p=3225

python是无法直接实现sendfile的,只能是借用PyObject + C语言实现。

讲解py库之前,先介绍下C语言的sendfile函数使用方法:


sendfile在两个文件描术符之间直接传递数据,完全在内核中操作,从而避免了内核缓冲区到用户缓冲区的拷贝,因此效率很高,称为零拷贝。
out_fd参数是待写入描述符。

in_fd参数是待读出的描述符。

offset参数指定从读入文件流的哪个位置开始读,如果为空,则从文件流的默认超始位置读入。

count参数指定传输的字节数。

调用成功时返回传输的字节数,失败则为-1,并设置errno .

需要注意的是,in_fd必须是进程打开文件后产生的文件描述符,你不能直接传入文件名,不能是socket和管道;而out_fd必须是一个socket。可见,sendfile专为网络传输文件而生。

python sendfile已经有个意大利的同学实现了,我们直接套用该模块就可以了。模块名是 pysendfile . 

再观摩下他的sendfilemodule.c的源码实现,可以看到sendfile函数并不是一次性把数据塞入到socket buffer,而是用while循环的copy到kernel socket端.  另外还针对EAGAIN做了及时返回。避免了阻塞读取写入的情况.  如果你有类似ioloop的调度实现,完全可以针对这事件进行io调度,当然如果是同步的逻辑,跟我上面的python实例一样,那么就无所谓了。

sendfile对于静态文件的处理是很高效的,也是web服务器必有的模式.  在python的主流web框架(tornado,flask,django)里默认是没有sendfile模块,原因是大多数的架构都是让nginx顶在python web框架前面的,原因不用废话。  按照实际应用的场景来描述,python sendfile更适合于client的角色,那么我写这篇关于web框架之python sendfile的用意是什么?学习性质的造轮子 !

END.



对Python及运维开发感兴趣的朋友可以加QQ群 : 478476595 !!!
{ 2000人qq大群内有各厂大牛,常组织线上分享及沙龙,对高性能及分布式场景感兴趣同学欢迎加入该QQ群 }

另外如果大家觉得文章对你有些作用!   帮忙点击广告. 一来能刺激我写博客的欲望,二来好维护云主机的费用.
如果想赏钱,可以用微信扫描下面的二维码. 另外再次标注博客原地址  xiaorui.cc  ……   感谢!
暂无相关产品

2则回应给“打造mvc框架之sendfile使静态文件高效传输”

  1. 在路上*2涛*说道:

    关于sendfile至今看到讲的最清楚的一个

发表评论