测试一个非常简单服务器如何达到100万(1M=1024K连接)的并发连接,并且这些连接一旦连接上服务器,就不会断开,一直连着。
环境受限,没有服务器,刚开始都是在自己的DELL笔记本上测试,凭借16G内存,和优秀的vmware workstation虚拟机配合,另外还得外借别人虚拟机使用,最终还得搭上两台2G内存的台式机(安装centos),最终才完成1M并发连接任务。
以前也做过类似的工作,量不大,没记录下来,一些压力测试和调优,随着时间流逝,早已忘记。这次是从零开始,基本上所有过程都会记录,一步一步,每一步都会遇到问题,并且给出相关解决问题的方法,最终完成目标。
为了方便,服务器端程序和客户端测试程序,都是使用C语言,不用像JAVA一样需要预先指定内存,感觉麻烦。使用较为原始的语言来写,可以避免不必要的调优工作。这中间,可能会穿插Java代码的思考方式。
可能需要懂点Linux,C,Java,假如您有更好的做法,或者建议,请直接告知,谢谢。
测试端和服务器端都选用较为熟悉的64位Centos 6.4,32位系统最多支持4G内存,太受限。IO密集型应用,对CPU要求不是很高。另外服务器确保安装上gcc,那就可以开工了。
所有端系统一旦安装完之后,默认不做任何设置。
服务器端程序依赖libev框架,需要提前编译,然后存放到相应位置。下面是具体服务器端代码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
|
编译
gcc server.c -o server ../include/libev.a -lm
运行
./server -p 8000
在源码中默认指定了8000端口,可以通过-p进行指定新的端口。 开启了8000端口进行监听请求,http协议处理类似于htmlfile chunked块编码传输。
测试程序使用libevent框架,因其使用简单,提供丰富易用接口,但需要提前下载,手动安装:
wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
tar xvf libevent-2.0.21-stable.tar.gz
cd libevent-2.0.21-stable
./configure --prefix=/usr
make
make install
注意make和make install需要root用户。
client1.c 源码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
|
备注:这部分代码参考了A Million-user Comet Application with Mochiweb, Part 3 ,根据需要有所修改。
编译
gcc -o client1 client1.c -levent
运行
./client1
可能在64位系统会遇到找不到libevent-2.0.so.5情况,需要建立一个软连接
ln -s /usr/lib/libevent-2.0.so.5 /lib64/libevent-2.0.so.5
即可自动连接IP地址为192.168.190.133:8000的服务器端应用。
测试端程序输出
看看测试端程序client1输出的错误信息:
Chunks: 798 Bytes: 402990 Closed: 0
Req: 192.168.190.133 -/test/900
Req: 192.168.190.133 -/test/1000
Chunks: 998 Bytes: 503990 Closed: 0
[warn] socket: Too many open files
[warn] socket: Too many open files
[warn] socket: Too many open files
服务器端程序输出
服务器端最后一条日志为
online user 1018
两边都遇到了文件句柄打开的情况。
在服务器端查看已经连接,并且端口号为8000的所有连接数量:
netstat -nat|grep -i "8000"|wc -l
1019
但与服务器端输出数量对不上,增加所有已经建立连接的选项:
netstat -nat|grep -i "8000"|grep ESTABLISHED|wc -l
1018
那么剩下的一条数据到底是什么呢?
netstat -nat|grep -i "8000"|grep -v ESTABLISHED
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN
也就是server.c监听的端口,数量上对的上。
在测试服务器端,查看测试进程打开的文件句柄数量
lsof -n|grep client1|wc -l
1032
再次执行
ulimit -n
1024
也是就是client1应用程序共打开了1032个文件句柄,而不是1024,为什么?
把当前进程所有打开的文件句柄保存到文件中,慢慢研究 lsof -n|grep client1 > testconnfinfo.txt
导出的文件可以参考: https://gist.github.com/yongboy/5260773
除了第一行,我特意添加上供友善阅读的头部列定义,也就是1032行信息,但是需要注意头部:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
client1 3088 yongboy cwd DIR 253,0 4096 800747 /home/yongboy/workspace/c_socket.io_server/test
client1 3088 yongboy rtd DIR 253,0 4096 2 /test_conn
client1 3088 yongboy txt REG 253,0 9697 799991 /home/yongboy/workspace/c_socket.io_server/test/test_conn_1
client1 3088 yongboy mem REG 253,0 156872 50404 /lib64/ld-2.12.so
client1 3088 yongboy mem REG 253,0 1922152 78887 /lib64/libc-2.12.so
client1 3088 yongboy mem REG 253,0 145720 76555 /lib64/libpthread-2.12.so
client1 3088 yongboy mem REG 253,0 47064 69491 /lib64/librt-2.12.so
client1 3088 yongboy mem REG 253,0 968730 26292 /usr/lib/libevent-2.0.so.5.1.9
client1 3088 yongboy 0u CHR 136,2 0t0 5 /dev/pts/2
client1 3088 yongboy 1u CHR 136,2 0t0 5 /dev/pts/2
client1 3088 yongboy 2u CHR 136,2 0t0 5 /dev/pts/2
client1 3088 yongboy 3u REG 0,9 0 4032 anon_inode
client1 3088 yongboy 4u unix 0xffff88007c82f3c0 0t0 79883 socket
client1 3088 yongboy 5u unix 0xffff880037c34380 0t0 79884 socket
client1 3088 yongboy 6u IPv4 79885 0t0 TCP 192.168.190.134:58693->192.168.190.133:irdmi (ESTABLISHED)
client1 3088 yongboy 7u IPv4 79889 0t0 TCP 192.168.190.134:58694->192.168.190.133:irdmi (ESTABLISHED)
client1 3088 yongboy 8u IPv4 79891 0t0 TCP 192.168.190.134:58695->192.168.190.133:irdmi (ESTABLISHED)
client1 3088 yongboy 9u IPv4 79893 0t0 TCP 192.168.190.134:58696->192.168.190.133:irdmi (ESTABLISHED)
可以看到文件句柄是从0u开始,0u上面的8个(5个mem + 3个启动)进程,1032 - 8 = 1024个文件句柄,这样就和系统限制的值吻合了。
root用户编辑/etc/security/limits.conf文件添加:
* soft nofile 1048576
* hard nofile 1048576
注意:
1024K x 1024 = 1048576K = 1M,1百万多一点。
备注:测试端和服务器端都需要作此设置,保存退出,然后reboot即可生效。
第一个问题,就这样克服了。再次运行 /client1测试程序,就不会出现受打开文件句柄的限制。但大概在测试端打开对外28200个端口时,会出现程序异常,直接退出。
段错误
这个也是程序没有处理端口不够用的异常,但可以通过增加端口进行解决。
备注: 但测试端单机最多只能打开6万多个连接,是一个问题,如何克服,下一篇解决此问题,并且还会遇到文件句柄的受限问题。
|