在上一篇中我们讲述了百万连接的测试过程及出现的问题和解决办法,有同学对其中的测试方法也有兴趣,我在这里再补充一下。这里的测试方法主要是指测试客户端如何发起百万连接并保持它们。由于受到单机单ip的端口数限制,即如下
pomelo@debian:~/socktest$ cat /proc/sys/net/ipv4/ip_local_port_range 2048 65500 |
单个客户端ip只能建立6万多连接,所以我们需要大约50个独立ip发起300万的连接。为简单起见,使用50台512M内存的虚拟机作为客户端。问题归结为两个方面:
1、单客户端如何建立并保持6万连接
2、如何控制几十个客户端
我们以java编写客户端代码。首先我们尝试的是一线程一连接的方式。这样在java中就需要维护6万个线程及其相关的对象,包括连接对象。很快我们就发现客户端java进程出现了OOM,512M内存不够用了。我们分析下测试目标,目的是保持6万个连接对象,在这种方式下我们相当于是使用了线程这种容器来保存这些对象,但由于线程本身的内存开销巨大,因此我们应该考虑换个轻量级的瓶子来装这些连接对象。
最终代码如下,即在一个线程内顺序建立连接,并将连接保存到一个数组中,至此就解决了上文问题中的一个方面
private static int n = 0; private static Socket[] sockList = null; static { n = Integer.valueOf(Config.getProperty("socket.num")); sockList = new Socket[n]; } public void connect(String host, int port) throws UnknownHostException { Socket so = null; long sleepTime = Integer.valueOf(Config.getProperty("socket.sleep")); for (int i=0;i<n;i++) { try { so = new Socket(host, port); sockList[i] = so; Thread.sleep(sleepTime); } catch (IOException e) { logger.error(e.getMessage()); } catch (InterruptedException e) { } } } |
接着,又是如何控制几十台客户端呢?其实比较简单,就是在shell脚本中通过ssh调用部署在客户端机器上的测试程序。主要有两个问题需要注意,一是ssh需要认证,我们可以在任意机器上产生无密码的ssh公私钥对,将公钥分发到客户端机器上。二是设置一个ip列表的配置文件。
这样,两个问题都解决了,可以开始测试了。测试过程及其问题不完全记录可以点这里。