网络监控方法
dstat命令,所代表的receive/send,貌似receive是接收的字节数,*8是带宽,而send并不是机器对外网发送的字节数,故不用它判断收发流量;
iftop命令,在实验场景下(每秒大约4个baidu首页请求,接收流量大约138KB*4),显示的发送和接收的流量,和程序计算的每秒发送接收流量基本一致,故采用这个命令,判断网络流量。
SS5日志
1、STARTED和TERMINATED是配对出现的,代表一次连接的开始和结束
[08/Apr/2015:19:46:57 CST] [1035835136] 10.10.96.106 "" "CONNECT" STARTED 0 0 0 (10.10.96.106:55389 -> 220.181.112.244:80)
[08/Apr/2015:19:48:03 CST] [1035835136] 10.10.96.106 "" "CONNECT" TERMINATED 23189 352 66 (10.10.96.106:55389 -> 220.181.112.244:80)
2、不是每一次代理请求都会被记录下来
当我们访问公网时,由于一次Socket请求(Client:IP+Port和Server:IP+Port)会延续较长时间,所以基本不会在1秒内被复用,所以基本都能记录日志;
当我们测试访问一个内网URL时,1秒内完成几百次成功的Socket请求,很多被复用,对于1秒内“Client:IP+Port和Server:IP+Port”相同的Socket,SS5认为是一个,只有1行日志;
这样,可以解释,访问内网URL时,几千个成功的请求,只有几百行日志的场景。
以上两种日志场景,我们都认为是正常的。
3、Socks method unknown or bad request
telnet 1080端口,输入字符;或者F5心跳检测1080端口,都会导致这个日志不断报出。这个应该通过更好的配置过滤掉。
性能指标
大并发情况下,Socket连接没有正常及时释放,或者到达临界值,如下错误报出。
日志会报如下错误(刷屏):
[08/Apr/2015:16:06:23 CST] [0] [ERRO] $S5ServerAccept$: (Too many open files).
[08/Apr/2015:16:06:23 CST] [1916823296] [ERRO] $S5GetClientInfo$: (Bad file descriptor).
程序会报如下错误:
java.net.SocketException: SOCKS server general failure
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:526)
at java.net.Socket.connect(Socket.java:529)
at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:411)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:525)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:208)
at sun.net.www.http.HttpClient.New(HttpClient.java:291)
at sun.net.www.http.HttpClient.New(HttpClient.java:310)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:987)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:966)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:841)
at cl.an.HttpConn.run(HttpSocketPressTest.java:188)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
性能测试结果:
Socket连接数-正常临界值(约值) | Socket连接数-异常临界值(约值) | 到达异常临界值后 | |
openfiles -1024 | 450 | 550 | 报上面的Bug,只保留200个线程,35秒后恢复正常 |
openfiles -4096 | 2000 | 2100-2500 | 第一种情况: ss5异常停止,不能恢复:service ss5 status,可以看到: ss5 已死,但是 subsys 被锁;有时还会报:*** glibc detected *** /usr/sbin/ss5: free(): invalid pointer: 0x00007f693c0207e0 *** 第二种情况: 报上面的Too many open files,只保留200个线程,10秒后恢复; |
openfiles -65536 | 结果和openfiles -4096类似 |
根据我们的测试结果,可以认为虚拟机10.100.140.85(4个CPU、6G内存),最大支持2000并发。
官网的性能指标是:IBM X360,支持2500并发数。
查看Socket连接数命令:netstat -napo | grep 1080 | wc -l
查看修改最大同时打开文件数命令:vim /etc/security/limits.conf ,需要新开一个终端,ulimit -n,确认生效了,service ss5 restart,才会在ss5中生生效。
关于这个值,很多公司这样设置:
[plain] view plain copy
* soft nofile 1000000
* hard nofile 1000000
* soft core 1048576
* hard core 1048576
参考网址:
http://www.codesky.net/article/201105/161796.html
http://www.justwinit.cn/post/6482/
http://blog.csdn.net/leili0806/article/details/7534985
压测结果
访问www.baidu.com(页面大小:135KB)
1、囿于带宽限制(实测、抢公网带宽,只能抢到1.5M-2M左右),所以,平均每秒,只可能有10-20个成功的Http请求返回。
2、会报java.net.SocketTimeoutException: Read timed out:这是因为网络带宽原因,Timeout时间内没有从流中读取完成数据所致的。这是正常的,网络原因,用不用Socket5代理都有这个问题。
3、会报java.net.ConnectException: Connection timed out: connect:也是网络原因,Timeout时间内,没有连接远程服务器成功。这是正常的,网络原因,用不用Socket5代理都有这个问题。
4、会报java.net.SocketException: Connection reset:怀疑是远程服务器的原因。
5、测试截图如下:
iftop:
dstat:
6、测试过程中,watch -n1 -d 'netstat -an | grep 1080',完全正常,SS5服务本身没有任何压力。
7、测试结果:
a、3个机器各开100个并发,成功率分别是:85%、65%、67%,失败的原因基本是Read timee out,即30秒不能完全从网络输入流中读取完成所有返回数据。
b、1个机器100个并发,成功率大约是98%。
访问内容URL
可以跑带宽大约50-60M,平均每秒250个成功返回,成功率100%,截图如下:
iftop:
dstat:
结论
SS5服务本身能承受巨大压力,调优ulimit -n后,大约支撑2000并发。
SS5服务,带宽足够,请求的文件越小,网络越好,就能支持更多的成功返回。