环境:centos,linux 2.6.18核。 lighttpd 1.4.28。php 5.2.17。

工具: http_load

lighttpd加载的module:

“mod_expire”,
“mod_rewrite”,
“mod_redirect”,
“mod_alias”,
“mod_access”,
“mod_status”,
“mod_fastcgi”,
“mod_compress”,
“mod_accesslog”

测试.htm后缀的文件,不经过fastcgi,运行多次,平均QPS为575。.php后缀的文件(仅echo短字符串),平均QPS为100+。

fastcgi配置为:

fastcgi.server             = (
                ".php" =>
                ( "localhost" =>
                  (
                   "socket" => "/usr/local/lighttpd/php-pid/php-fastcgi.socket",
                   "bin-path" => "/usr/local/php-cgi/bin/php-cgi -c /etc/php.ini",
                   "max-procs" => 10,
                   "bin-environment" => (
                           "PHP_FCGI_CHILDREN" => "10",
                           "PHP_FCGI_MAX_REQUESTS" => "5000"
                           ),
                   "bin-copy-environment" => ( "USER" ),
                   "broken-scriptfilename" => "enable"
                  )
                ),
                ".html" =>
                ( "localhost" =>
                  (
                   "socket" => "/usr/local/lighttpd/php-pid/php-fastcgi.socket-0"
                  )
                )
        )

这时,每个php-cgi进程占用的vss内存为5m左右(其中包含了共享lib的内存)。一共启动的php-cgi个数为:(max-procs+1)× PHP_FCGI_CHILDREN。其中max-procs个父进程并不真正处理http请求。

遇到一个奇怪的问题,尝试将PHP_FCGI_CHILDREN增大到100,即启动550个php进程。再重启lighttpd的时候,虚拟机直接挂死(kill)。

猜测可能是中止lighttpd的时候,其会进行一系列的后缀处理,而进程太多,消耗内存和fd过多而至的(不确定)。

这时,即使再加大http_load的压力,也无法取得更好的QPS了。查看http://127.0.0.1/server-counters又发现一个奇怪的现象,即fastcgi.backend.localhost.9.connected占据了90%+的连接数。是由于长连接的问题吗?但是将server.max-keep-alive-requests设置为0,还是这种情况。

http://redmine.lighttpd.net/boards/2/topics/2027看到如下解释:

In 1.4.x lighty tends to stick to one backend, which is not really a bad thing, as this backend probably has a better cache than the other backends. It will move ofc to another one if one backend isn´t avail or loaded.

集中在相同的php backend,是为了最大限度的利用缓存,而当负载过重或不可用时,它会自动切换到其他php backend。ok,我接受这种解释。

最后,我调整了如下的参数:

server.max-keep-alive-requests=16 # maximum number of request within a keep-alive session

server.max-keep-alive-idle = 5 # 无动作保持连接的超时时长

server.max-read-idle = 60 # 读取被阻塞的超时时长

server.max-write-idle = 360 # 写数据被阻塞的超时时长(大文件的读写会被trunk,针对每个trunk计算时长)

server.max-fds = 4096 # 最多可打开的文件描述符个数(包括socket、本地文件等)

server.max-connections = 2048 # 最多连接数(lighttpd本身进程的限制)

server.stat-cache-engine = “fam” # stat的缓存方式,需要在编译lighttpd时候指定–enable-fam

由于我认为线上服务器的fd是宝贵的,希望每个fd能够尽可能多的服务于不同的users,而不是为了一个users keep alive等待。

所以我减少了keep alive的可能性。

而由于线上的errorlog中经常出现“sockets disabled, connection limit reached ”,说明socket不够用,

间接说明文件描述符不够用,所以我调大了fd的上限。因为可用连接数=fd上限/2。

lighttpd需要同user间通过socket建立连接,也需要同php-cgi间通过原始套接口建立连接,其实还需要一些其他连接,比如log等。

所以得出上述公式。

此外,系统本身也有限制,查看Linux的最大文件描述符:
# cat /etc/redflag-release
Red Flag DC Server release 5.0 (Trinity SP2)


# cat /proc/sys/fs/file-nr
580     0       131072
三个值的意思分别是:
580:总共打开的文件描述符的数量(从系统开机开始算, 所有打开的文件描述符的数量)
0:总共的空闲的文件描述符的数量
131072:最大能打开的文件描述符的数量


修改:
# echo “132096″ > /proc/sys/fs/file-max
或加入/etc/sysctl.conf文件中。

我猜测的lighttpd处理流程:

1、用户输入url,尝试连接lighttpd web server

2、如果lighttpd已经达到了最大连接数max-connections,则用户无法连接,一直在等待(可以将max-connections配置为很小的数值看看)

3、lighttpd检查该url是否正确,是否需要被php-cgi处理

4、如果需要且有空闲的php-cgi,将处理权交给php-cgi

5、如果没有空闲的php-cgi,则压入队列,等待

所以,王道还是配置合理的php-cgi数目,并且减少php的处理时间!!

ps:查看lighttpd连接情况 sudo netstat -punt | grep lighttpd

为了监测每个响应的时长,可以使用如下配置:其中%T是time used in seconds。更精准的%D目前不支持。

accesslog.format = “%h^F%V^F%u^F%t^F%T^F\”%r\”^F%>s^F%b^F\”%{Referer}i\”^F\”%{User-Agent}i\””

————————————————————

2011-3-23

仍然在虚拟机针对本机压力测试(没机器,就是可怜)。

针对某页面A(7.7k),直接访问数据库,无缓存。http_load -parallel 100 -fetches 1000 local.txt多次运行结果为54QPS。运行期间,load average较重,cpu100%,其中wa占到80%左右。

对memcached进行基准测试:针对另一页面B,仅从memcache中获取一次数据,不输出。当数据是MEMCACHE_COMPRESSED 存入的时候,http_load -parallel 100 -fetches 1000就会导致大批量的memcache->get失败:Failed reading line from stream。改为不压缩存入,则结果为100QPS(偶尔还是会有连接失败的情况)。

仍然针对页面A,部分数据修改为访问memcache,部分访问数据库。仍然不行,当memcached无法连接的时候,压力又转嫁到mysql上,http_load总是报无法连接的错误。这种情况,应该不是mysql、memcached或者php-memcache的问题,而是我本机是笔记本的虚拟机,性能太差。

最后,做页面的静态化,将页面A保存为.htm后缀,不经过php-cgi。结果为747QPS,且系统负载很轻。所以坚定了要对部分页面做完全静态化的信念。

可以通过lighttpd的rewrite来重定向动态url到静态,如 “^/try/$” => “/index.htm”,

Leave a Reply