加载中…
个人资料
王斌科
王斌科
  • 博客等级:
  • 博客积分:0
  • 博客访问:36,216
  • 关注人气:163,639
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

为什么Nginx处理静态数据的性能十分优秀??

(2013-05-30 22:10:10)
分类: 系统架构
        一直听说Nginx在处理静态数据方面的能力十分优秀,但是没有深入进行刨根问底,近期学习Nginx模块开发,加入Nginx开发邮件列表,通过对大牛们的问题的琢磨以及学习,对这个问题有了稍微深入一点的认识。

        首先,得益于Linux内核提供的文件异步I/O和ngx_epoll_module模块中实现的针对文件的异步I/O。这里提到的文件异步I/O并不是glibc库提供的文件异步I/O,glibc库提供的异步I/O是基于多线程实现的,它并不是真正意义上的异步I/O。这里说的异步I/O时由Linux内核实现,只有在内核中成功地完成了磁盘操作,内核才会通知进程,进而使得磁盘文件的处理与网络事件的处理同样高效。Linux内核版本2.6.2x以后支持文件异步I/O,Nginx把读取文件的操作异步地提交给内核后,内核会通知I/O设备独立地执行操作,这样,Nginx进程可以继续充分地占用CPU,而且,当大量读事件堆积到I/O设备的队列中时,将会发挥出内核中“电梯算法”的优势,从而降低随机读取磁盘扇区的成本。Nginx仅支持在读取文件时使用异步I/O,因为正常写入文件时往往时写入内存中就立刻返回,效率很高,而使用异步I/O写入时速度会明显下降。

        其次,Linux SendFile系统调用带来的优势。Nginx启用了Linux上的SendFile系统调用来发送文件,它减少了内核态与用户态之间的两次内存复制,这样就会从磁盘中读取文件后直接在内核态发送到网卡设备,提高了发送文件的效率。

        要搞明白sendfile的原理,必须弄明白这样一个问题,数据是如何发送的?也就是数据从主机进入线路之前所发生的一切。

        1、应用程序首先得将要发送的数据写入该进程的内存地址空间中。
        2、应用程序通过系统函数库接口(如send函数)向内核发出系统调用,由系统内核来进行随后的操作,它将这些数据从用户态内存区复制到由内核维护的一段称为内核缓冲区的内存地址空间,也就是内核态。这块地址空间的大小通常是有限的,所有要发送的数据都将以队列的形式进入到这里,这些数据可能来自于多个进程,每块数据都有一定的记号来标记它们的去向。如果要发送的数据比较多,那么系统调用需要进行多次,每次复制一定的数据大小,这个大小取决于网络数据包的大小以及内核缓冲区的承载能力。重复的系统调用体现在应用编程层面重复调用send函数。

        3、当数据写入内核缓冲区以后,内核将通知网卡控制器来取数据,同时CPU转而处理其他进程。网卡控制器接到通知后,便根据网卡驱动器信息得知对应内核缓冲区的地址,将要发送的数据复制到网卡的缓冲区中。这系列的数据复制中,数据始终按照连接两端设备的内部总线宽度来复制,采用PCI-X总线接口的网卡一般使用32位总线宽度,那么从内核缓冲区到网卡缓冲区的数据复制过程中,任何时刻只能复制32位的比特信息。

        4、网卡缓冲区中的数据需要发送到线路中,同时释放缓冲区来索取更多要发送的数据,只有二进制的数字信号才能在线路中传输,所以这时候需要对数据进行字节到位的转换。

        5、发送时,网卡会使用内部特定的物理装置来生成可以传播的各种信号(光信号、电信号)。

       

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有