前面的文章说过,用libevent这类事件机制,写个server支持几万并发并不难。
libev是libevent的改进版,EV是libev的Perl封装模块,作者基于EV实现了一个很NB的事件框架,叫做AnyEvent。
用AnyEvent写个简单webserver,支持几万并发很轻松。
如下是示例代码:
use AnyEvent::HTTPD;
my $httpd = AnyEvent::HTTPD->new (port => 9090);
$httpd->reg_cb (
‘/’ => sub {
my ($httpd, $req) = @_;
$req->respond ({ content => [‘text/html’,
“<html><body><h1>Hello World!</h1>”
. “<a href=\”/\”>test page by pyh</a>”
. “</body></html>”
]});
},
);
$httpd->run;
把上述代码存为httpd.pl,运行perl httpd.pl,一个webserver就产生了,侦听在9090端口。
为了支持更高并发,在web服务器上,Linux内核简单调整如下参数:
net.core.somaxconn = 1024 # 挂起请求最大数量
net.core.netdev_max_backlog = 3000 # 进入包最大设备队列
net.ipv4.tcp_max_syn_backlog = 81920 # syn队列长度
net.ipv4.tcp_wmem = 8192 436600 873200 # TCP写缓存
net.ipv4.tcp_rmem = 32768 436600 873200 # TCP读缓存
我们用ab做压力测试,由于ab默认最大支持2W并发,因此如下修改ab源代码:
(1)
/* catch legitimate fatal apr_socket_recv errors */
else if (status != APR_SUCCESS) {
err_recv++;
if (recverrok) {
bad++;
close_connection(c);
if (verbosity >= 1) {
char buf[120];
fprintf(stderr,”%s: %s (%d)\n”, “apr_socket_recv”, apr_strerror(status, buf, sizeof buf), status);
}
return;
} else {
apr_err(“apr_socket_recv”, status);
bad++;
close_connection(c);
return;
}
}
上述橙色标明的是新增加的部分。
(2)
#define MAX_CONCURRENCY 50000 //最大并发数,原来是20000,改为50000
改完后,重新编译ab。
用ab对webserver执行压力测试,共50000个请求,50000个并发:
./ab -n 50000 -c 50000 http://example.com:9090/
测试结果如下图。50000个请求全部成功,每秒请求1150个,服务器端压力几乎为0.
所以,事件驱动的网络服务,高并发说明不了什么问题。