Search This Blog

2014-04-20

生成并保持100万HTTP连接

最近的一个项目需要支持100万客户端同时拉消息,一开始只是做了一个原型,测试的时候准备用一个客户端请求某个url地址生成100万连接并且保持住(服务器端已经把相应处理器的HTTP超时时间设置到7天),同时用压力测试工具来请求另外一个url地址,然后根据监控情况看看服务器的各种资源消耗。

对于这样一个客户端,有以下几个条件需要满足:
  1. 一个请求对应一个线程的模型肯定是不行的,开不了这么多线程。纯Java方式来实现的话,只能考虑异步API
  2. 同时请求太多的话,肯定会有失败的,应该尽量减少失败,所以需要控制请求速率
  3. 最好在一台机器产生这么多请求,否则的话,不方便测试

先试了Apache HttpClient,包括HttpAsyncClient跟httpcore-nio,都不适合。具体可以参考org.apache.http.examples.nio.client.AsyncClientHttpExchangeFutureCallback.java跟org.apache.http.examples.nio.NHttpClient.java。

然后看了Netty3,在org.jboss.netty.example.http.snoop.HttpSnoopClient.java基础上改改即可,满足上面的3个条件:
  1. 是异步API
  2. 由于是异步API,发完请求不会被阻塞,sleep(1ms)即可大概控制在1000req/s
  3. 一个ip最多只能使用65535个端口,不够100万
    • 通过ifconfig生成17个虚拟ip(比如 /sbin/ifconfig eth0:1 192.168.100.1 up )
    • 通过 /etc/sysctl.conf 里面的 net.ipv4.ip_local_port_range 调整端口号范围(有60K+可用),把fs.file-max跟fs.nr_open都改大到400万,"sudo /sbin/sysctl -p"之后生效;修改 /etc/security/limits.conf 里面的nofile,必须小于前面设置的fs.nr_open,登出系统生效;
    • 通过 ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port), new InetSocketAddress(localHost, 0)); 绑定HTTP请求ip,localHost就是192.168.100.1之类的ip地址。顺便提一下ip绑定,比如新版本Tomcat的8005端口就是绑定到localhost上的,只能在本机访问,老版本是出过问题的
连接过程就在主线程跑,每个ip发起60K个请求。
在服务器本机运行这个客户端,生成100万连接不到20分钟。

后来看jetty文档的时候看到http://www.eclipse.org/jetty/documentation/current/http-client-api.html#http-client-async,看起来也是可以的,没有试验过。

=文章版本=

20140411

No comments:

Post a Comment