`
freeway2000
  • 浏览: 25539 次
社区版块
存档分类
最新评论

基于Netty的Comet测试及调优

阅读更多

 

测试环境:

 

服务器 1

  OS: Red Hat Enterprise Linux Server release 5.4

  CPU: 4xIntel(R) Xeon(R) CPU E5450 @ 3.00GHz

  MEMORY:4G

客户端5台,配置同服务器

上述的测试环境都是采用的虚拟机,而且虚拟机性能不是很好,所以我主要是测连接数,其中有涉及到性能的地方不具可参考性。另外Comet需要关注的是它能支撑的连接数个数,而并非qps,当然qps也是我们需要考虑的性能点之一。

 

 

服务端环境配置

 

JDK版本1.6.0_18

Netty版本3.2.2

 

sudo vi /etc/sysctl.conf

加入如下配置:

 

net.core.somaxconn = 2048
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.somaxconn = 10000
net.core.netdev_max_backlog = 20000

net.ipv4.tcp_rmem = 7168 11264 16777216
net.ipv4.tcp_wmem = 7168 11264 16777216
net.ipv4.tcp_mem = 786432 2097152 3145728
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_max_orphans = 131072
net.ipv4.tcp_max_tw_buckets=180000
fs.file-max = 1000000
 

编辑完成后执行如下命令让配置生效

sudo /sbin/sysctl -p

 

sudo vi /etc/security/limits.conf 

找到hard nofile和soft nofile配置信息,修改为如下:

*  hard nofile 1000000
*  soft nofile 1000000

 

客户端环境配置

 

由于系统默认参数,自动分配的端口数有限,是从32768到61000,所以我们需要更改客户端/etc/sysctl.conf的参数:

 

net.ipv4.ip_local_port_range = 1024 65535

 

编辑完成后执行如下命令让配置生效

sudo /sbin/sysctl -p

客户端程序是基于libevent写的一个测试程序,不断的建立新的连接请求。客户端与服务端需要建立大量的socket,所以我们需要调速一下最大文件描述符。客户端,需要创建六万多个socket,我设置最大为十万,在 /etc/security/limits.conf 中添加

 

*  hard nofile 1000000
*  soft nofile 1000000

 

 

java的内存调优

 

对于java的内存管理,肯定离不开GC的调优。长连接是一个长期占用内存的一种应用,直到连接中断才会被释放。如果按照传统的方式来分配Eden、S0、S1是存在问题的,如果按照默认的配置Eden空间大于Survivor,那么在进行GC的时候由于长连接所占用的内存并不释放,导致Survivor空间无法容纳,收集器会将无法容纳的数据丢入到Old区。

 

为了验证这个情况作了一个测试,java的配置参数如下:

-server -Xms1G -Xmx1G -XX:PermSize=64m -XX:+UseParallelGC -XX:+UseParallelGC -verbose:gc -XX:+PrintGCDetails

运行之后jstat日志信息如下,关注其中的红色部分,进行minor GC的时候由于S1的空间不够容纳,收集器将无法容纳的数据丢入到Old区,如果持续下去,会频繁进行Full GC,这是我们不想看到的。

 

 

  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT  

  0.00   0.00  98.00   0.00   8.78      0    0.000     0    0.000    0.000

  0.00  99.93   9.94   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93   9.94   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93   9.94   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93   9.94   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93   9.94   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93   9.94   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  13.84   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  25.08   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  37.62   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  48.86   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  51.46   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  62.70   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  66.60   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  77.84   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  79.14   9.20   8.78      1    0.195     0    0.000    0.195

  0.00  99.93  90.39   9.20   8.78      1    0.195     0    0.000    0.195

 99.93   0.00   7.17  26.40   8.78      2    0.511     0    0.000    0.511

 

实际在线上的应用场景,连接每隔一段时间就会关闭。那么仍到Old区的内存几乎每次都能够完全回收,但是交给Old区来回收实在是太重了,如何避免频繁的Full GC是我们需要关注的。

 

接下来另外的一种配置方式,淘宝韩彰分享过这种做法。加大Survivor区,让Survivor区的空间和Eden空间一样大,这样可以保证在minor GC的时候数据不会放入到Old区。下一次执行minor GC的时候,先前的Survivor区的数据可以完全回收掉。

PS:前提是minor GC周期必须大于一个连接的生命周期,比如一个连接每隔30s会关闭,那么两次minor GC的时间间隔必须大于30s。

 

测试

 

最后,为了测试Netty支持最大的连接数,我们配置如下:

 

-server -Xms4G -Xmx4G -XX:NewSize=3584m -XX:PermSize=64m -XX:SurvivorRatio=1 -XX:+UseParallelGC -XX:-UseAdaptiveSizePolicy

Eden、S0、S1各1G,Old512M,UseParallelGC回收机制,加入UseAdaptiveSizePolicy不允许回收器自动调整Eden和Survivor区大小。

 

启动服务端的comet进程后,初始的对象占用 167.26MB。然后启动客户端连接到服务端,每个客户端建立6w个连接。当客户端的连接数达到 6w左右的时候就不能再连接了。

 

执行server端的dmesg命令,发现存在如下信息:

 

ip_conntrack: table full, dropping packet.

再执行如下命令

sudo cat /proc/sys/net/ipv4/ip_conntrack_max

是65322,看来是最大连接跟踪值开得较小了。

 

接下来执行sudo vi /etc/sysctl.conf 进行编辑,加入如下配置:

 

net.ipv4.ip_conntrack_max = 1000000   //设置最大连接跟踪值
net.ipv4.netfilter.ip_conntrack_max=1000000 
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait=120 
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait=60 
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait=120

再从新进行测试,现在连接已经可以突破6w了。

 

 

当生成12万个连接后,内存占用1194.75MB。

也就是说每个连接占用8.8k  = (1194.75-167.26)*1024/120000

这只是纯粹的连接,还没有涉及到数据的传输,一旦涉及到数据的传输,每个连接占用的内存肯定会超过8.8k

 

当超过12万之后java进程会进行一次minor GC,耗时1.11秒(用的是虚拟机,线上环境应该会好上几倍)

具体信息如下:

398.120: [GC [PSYoungGen: 1223424K->504705K(2446720K)] 1223424K->504705K(2971008K), 1.1087630 secs] [Times: user=2.45 sys=0.81, real=1.11 secs] 

 

持续增加连接,当增加到26万个连接系统仍然表现稳定。

 

当连接数达到27万左右的时候java进程进行了第二次minor GC,由于是一直保持着的长连接,数据是不会被释放的,此时杯具的事情发生了:

 

下面是第二次minor GC的信息

 

  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT

  0.00  41.26 100.00   0.00   8.81      1    1.109     0    0.000    1.109

  5.51  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 21.86  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 40.32  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 56.11  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 67.12  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 78.00  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 80.87  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 80.92  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 80.92  41.26 100.00   0.00   8.81      2    1.109     0    0.000    1.109

 .....

 86.05   0.00  29.31   0.00   8.90      2  588.199     0    0.000  588.199

 

最终耗时587s,不可想象啊!

 

1777.982: [GC [PSYoungGen: 1728129K->1052673K(2446720K)] 1728129K->1052673K(2971008K), 587.0906510 secs]
 

结论:

上述测试场景下最多能够支撑26万左右的长连接。超过26万就会出现上述第二次minor GC的情况,可用性无法得到保障。

 

在真实场景下,并不是真正的保持长连接状态,当连接了一定的时间,连接会关闭掉。假如设定每个连接每隔30s会关闭,那么你只需要保证minior GC的周期大于30s就可以避免上述第二次minor GC的情况。因为放入到S1中的数据一定能在下一个GC周期内全部释放掉。

 

目前的测试场景还不能完全反映和还原线上真实场景,真实场景下有着各种复杂的情况,数据传输对内存的占用也会不一样。线上的连接数肯定要打折扣。

 

如果 minor GC 的周期大于30s,保守估计一个netty进程大概能支持10万左右长连接(1G的Eden空间的能容纳12万个连接)。

 

另外,感谢淘宝 李子 在整个测试过程中予以的帮助。


2
1
分享到:
评论
3 楼 clongjava 2012-08-01  
lion_king 写道
请问有netty的comet例子吗?谢谢

同问,有的话分享下哦
2 楼 milk_36 2012-07-31  
很有意思的测试,至少让我心里有个底了...
1 楼 lion_king 2011-09-21  
请问有netty的comet例子吗?谢谢

相关推荐

    JAVA版基于netty的物联网高并发智能网关.zip

    JAVA版基于netty的物联网高并发智能网关 JAVA版基于netty的物联网高并发智能网关 JAVA版基于netty的物联网高并发智能网关 JAVA版基于netty的物联网高并发智能网关 JAVA版基于netty的物联网高并发智能网关 JAVA...

    基于netty+websocket+springboot的实时聊天系统项目源码.zip

    1、基于netty+websocket+springboot的实时聊天系统项目源码.zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料...

    TCP调试助手(基于Netty)

    对于开发者而言,【TCP调试助手(基于Netty)】不仅可以用于日常的TCP协议调试,还能在开发和测试网络服务时,快速定位问题,提高工作效率。通过深入理解和运用Netty框架,可以进一步提升TCP调试工具的功能性和灵活性...

    基于Netty实现的命令行斗地主游戏,为划水摸鱼而生.zip

    基于Netty实现的命令行斗地主游戏,为划水摸鱼而生~ 基于Netty实现的命令行斗地主游戏,为划水摸鱼而生~ 基于Netty实现的命令行斗地主游戏,为划水摸鱼而生~ 基于Netty实现的命令行斗地主游戏,为划水摸鱼而生...

    基于Netty实现CometStreaming方式的聊天室

    Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。本篇将深入探讨如何利用Netty实现CometStreaming方式的聊天室。 首先,我们要理解CometStreaming是什么。...

    基于Netty的Java数据采集软件

    《基于Netty的Java数据采集软件详解》 在IT领域,高效、稳定的数据采集系统是许多业务场景中的关键环节。本文将深入探讨一个基于Netty的Java数据采集软件,它利用Netty强大的网络通信框架,实现了对大规模分布式...

    基于netty实现的web框架

    【标题】:“基于Netty实现的Web框架” 在IT领域,构建高性能、高并发的网络应用是关键。Netty作为一个强大的异步事件驱动的网络应用框架,为Java开发者提供了高效且灵活的基础,使得构建Web框架变得更为便捷。本...

    基于netty编写的socket服务端

    Socket编程是网络通信的基础,而Netty则为构建基于Socket的服务端提供了强大的支持。 Netty的核心在于其使用了非阻塞I/O(Non-blocking I/O,也称为NIO)模型,这使得它在处理大量并发连接时表现出色。NIO是一种I/O...

    基于Netty实现了dubbo rpc

    【标题】基于Netty实现Dubbo RPC 在分布式系统中,RPC(Remote Procedure Call)是一种常见且重要的通信机制,它允许一个程序调用另一个在不同进程中运行的程序,就像调用本地函数一样简单。Dubbo作为阿里巴巴开源...

    Netty性能测试

    在“Netty性能测试”中,我们关注的是Netty在处理并发请求时的能力,以及它作为RPC(远程过程调用)框架的表现。 Netty 的高性能主要体现在以下几个方面: 1. **异步IO模型**:Netty采用了NIO(非阻塞I/O)模型,...

    毕设项目:基于netty+websocket+springboot的实时聊天系统.zip

    毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+...

    基于Netty框架开发的Modbus源代码。

    基于Netty框架开发的Modbus源代码。支持 * READ COILS | 0x01 * READ DISCRETE INPUTS | 0x02 * READ HOLDING REGISTERS | 0x03 * READ INPUT REGISTERS | 0x04 * WRITE SINGLE COIL | 0x05 * WRITE SINGLE REGISTER...

    Java版基于Netty框架的远程控制程序及源代码

    基于Netty框架的远程桌面控制程序,压缩文件包含可执行jar包、源代码jar包和依赖的netty4jar包,jdk版本为1.7,双击MyRemoteControllerV2-1.0.jar可直接运行,最好在两台机子上测试,当然单机也可以测试,只不过有些...

    基于 Netty 开发的 Java 游戏服务端框架,目前提供 CocosCreator 和 Unity 的客户端SDK.zip

    基于 Netty 开发的 Java 游戏服务端框架,目前提供 CocosCreator 和 Unity 的客户端SDK.zip 基于 Netty 开发的 Java 游戏服务端框架,目前提供 CocosCreator 和 Unity 的客户端SDK.zip 基于 Netty 开发的 Java 游戏...

    基于Netty实现的内网穿透&反向代理的工具 (支持TCP上层协议和HTTP的穿透式反向代理).zip

    基于Netty实现的内网穿透&反向代理的工具 (支持TCP上层协议和HTTP的穿透式反向代理).zip

    基于netty的安全即时通讯系统源码+项目说明.zip

    基于netty的安全即时通讯系统源码+项目说明.zip基于netty的安全即时通讯系统源码+项目说明.zip基于netty的安全即时通讯系统源码+项目说明.zip基于netty的安全即时通讯系统源码+项目说明.zip基于netty的安全即时通讯...

    基于netty封装的快速分布式任务开发框架

    【基于Netty封装的快速分布式任务开发框架】是一种高效、轻量级的解决方案,它将Netty的强大功能与分布式任务处理的灵活性相结合。Netty是一个高性能的异步事件驱动的网络应用程序框架,常用于构建高度可扩展的网络...

    基于Netty5.0的高级案例NettyWebsocket

    "基于Netty5.0的高级案例NettyWebsocket" 这个标题揭示了我们将会探讨一个使用Netty 5.0框架实现的WebSocket服务器的高级应用场景。Netty是一个高性能、异步事件驱动的网络应用程序框架,主要用于快速开发可维护的高...

    基于Netty手写Dubbo框架

    基于Netty手写Dubbo,该资源包含 1、生产者向zk服务的注册,消费者发现服务。 2、RPC远程调用实现。 3、netty服务调用,对象序列化和反序列化。 4、负载均衡的简单实现 详情见博客:...

Global site tag (gtag.js) - Google Analytics