热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

澄清对nginx的fastcgi性能的一个误解

在网上看到有一篇帖子,大概讲到lighttpd、apache和nginx对fastcgi的处理方式。其中提到nginx的缺点是由于使用了较小的缓冲区,所以每访问一个帖子时,会向后端多次读取,从而影响了性能。相比之下lighttpd会把后端返回内容一次性照单全收,所以较快。不过

在网上看到有一篇帖子,大概讲到lighttpd、apache和nginx对fastcgi的处理方式。其中提到nginx的缺点是由于使用了较小的缓冲区,所以每访问一个帖子时,会向后端多次读取,从而影响了性能。相比之下lighttpd会把后端返回内容一次性照单全收,所以较快。

不过照我的理解,fastcgi后端返回的数据通常是一个流(stream),流的大小是未知的,所以无法理解lighttpd为什么能一次性读完这个流,所以,lighttpd在流开始传输时也不可能知道流的大小,所以在读取过程中,也会是利用buffer size循环读取的。有所不同的是,lighttpd会有一个内存区用于存放所有的返回内容,这会增加内存的占用,不过有趣的是,lighttpd正是利用此内存区实现了“瞬间缓存”。而nginx没有此内存区,它完全是使用流的方式输入输出,并通过filter过滤器实现对流的处理,应说技术实现上更为先进,你可知如何在一个流上采用正则表达式做字符串替换?

多次读取流会不会影响到性能呢?这个问题在两个阵营征战了很多年了,在数年前,就有在java编程中是否采用ResultSet直接读取或是将数据库数据结果集完全读入序列化object(HashMap+ArrayList/数组)之争,在我看来,直接用ResultSet性能和稳定性是最好的,但程序撰写上就有一点麻烦,使用HashMap方式的话相对开发就比较轻松,但它并不可以提供最好的性能。有人一直坚持HashMap拥有高性能的说法,我对此不敢苟同:他的意思是,用HashMap接收完成后数据库就可以关闭链接,而ResultSet只能在线程结束(页面完成)时才能关闭链接,所以用HashMap会更省数据库压力;但是别忘了,HashMap这样的对象可是内存大户,在我的机器上,用HashMap与不用HashMap单个java进程会相差一倍的内存占用(约400M),可见其恐怖,用如此巨大的内存去换取数据库关闭链接的一点时间是不怎么划算的。

除了数据库,我在网络文件和本地文件的读取上,也做过有趣的测试,譬如下载一个静态文件,静态文件是有content-length头的,所以很容易知道它的大小。我分别取用byte=1和byte=content-length两种情况去下载这个文件,显然,假设文件有1k大小,byte=1会经过1024次循环,而byte=content-length只有一次循环,所以理论上byte=1会严重影响性能,但结果这两者并没有显著的差别,有个朋友最近做了一个爬虫,用C语言写的,每线程直接开出20M内存,我对此不能理解,如果是这样,我不如拿个curl或者wget来下还省得多了。

在本地文件的读取上,处理的文件体积有时比网络上的更恐怖,如access_log,这时是不可以使用文件大小那么大的buffer size的,因为机器的内存一般只有一两个G,要把动辄数G的access_log完全读入内存是不可以的,所以在大文件的处理上无可非议只能用较小的buffer size去处理,在java中,我一般使用BufferedReader的readLine方式处理log文件,一般100M的文件在几秒就能处理完,几乎不亚于C语言的速度。

所以,使用循环多次读流的方式并不会严重影响性能,而且这也是计算机发展上比较先进的做法。所以nginx采用这种方式并不稀奇,各位看官也没有必要把nginx的buffer size调得很高,免得适得其反,我现在按默认的4k,基本就能工作得很好了。我倒是担忧lighttpd将后端数据全部读入内存的做法,如果并发数据量超过机器容量时,稳定性该如何保障呢?


推荐阅读
author-avatar
爱在西元前2502938591
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有