基于Netty的Comet测试及调优

2024-02-27 13:18
文章标签 测试 netty 调优 comet

本文主要是介绍基于Netty的Comet测试及调优,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://freeway2000.iteye.com/blog/1137891

测试环境:

 

服务器 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

加入如下配置:

 

Shell代码   收藏代码
  1. net.core.somaxconn = 2048  
  2. net.core.rmem_default = 262144  
  3. net.core.wmem_default = 262144  
  4. net.core.rmem_max = 16777216  
  5. net.core.wmem_max = 16777216  
  6. net.core.somaxconn = 10000  
  7. net.core.netdev_max_backlog = 20000  
  8.   
  9. net.ipv4.tcp_rmem = 7168 11264 16777216  
  10. net.ipv4.tcp_wmem = 7168 11264 16777216  
  11. net.ipv4.tcp_mem = 786432 2097152 3145728  
  12. net.ipv4.tcp_max_syn_backlog = 16384  
  13. net.ipv4.tcp_fin_timeout = 15  
  14. net.ipv4.tcp_max_syn_backlog = 16384  
  15. net.ipv4.tcp_tw_reuse = 1  
  16. net.ipv4.tcp_tw_recycle = 1  
  17. net.ipv4.tcp_max_orphans = 131072  
  18. net.ipv4.tcp_max_tw_buckets=180000  
  19. fs.file-max = 1000000  
 

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

sudo /sbin/sysctl -p

 

sudo vi /etc/security/limits.conf 

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

Shell代码   收藏代码
  1. *  hard nofile 1000000  
  2. *  soft nofile 1000000  

 

客户端环境配置

 

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

 

Shell代码   收藏代码
  1. net.ipv4.ip_local_port_range = 1024 65535  

 

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

sudo /sbin/sysctl -p

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

 

Shell代码   收藏代码
  1. *  hard nofile 1000000  
  2. *  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支持最大的连接数,我们配置如下:

 

Shell代码   收藏代码
  1. -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命令,发现存在如下信息:

 

Shell代码   收藏代码
  1. ip_conntrack: table full, dropping packet.  

再执行如下命令

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

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

 

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

 

Shell代码   收藏代码
  1. net.ipv4.ip_conntrack_max = 1000000   //设置最大连接跟踪值  
  2. net.ipv4.netfilter.ip_conntrack_max=1000000   
  3. net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait=120   
  4. net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait=60   
  5. 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,不可想象啊!

 

Log代码   收藏代码
  1. 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万个连接)。

 

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


这篇关于基于Netty的Comet测试及调优的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/752512

相关文章

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

JVM内存调优原则及几种JVM内存调优方法

JVM内存调优原则及几种JVM内存调优方法 1、堆大小设置。 2、回收器选择。   1、在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM。   2、对JVM内存的系统级的调优主要的目的是减少

Verybot之OpenCV应用一:安装与图像采集测试

在Verybot上安装OpenCV是很简单的,只需要执行:         sudo apt-get update         sudo apt-get install libopencv-dev         sudo apt-get install python-opencv         下面就对安装好的OpenCV进行一下测试,编写一个通过USB摄像头采

BIRT 报表的自动化测试

来源:http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-birttest/如何为 BIRT 报表编写自动化测试用例 BIRT 是一项很受欢迎的报表制作工具,但目前对其的测试还是以人工测试为主。本文介绍了如何对 BIRT 报表进行自动化测试,以及在实际项目中的一些测试实践,从而提高了测试的效率和准确性 -------

可测试,可维护,可移植:上位机软件分层设计的重要性

互联网中,软件工程师岗位会分前端工程师,后端工程师。这是由于互联网软件规模庞大,从业人员众多。前后端分别根据各自需求发展不一样的技术栈。那么上位机软件呢?它规模小,通常一个人就能开发一个项目。它还有必要分前后端吗? 有必要。本文从三个方面论述。分别是可测试,可维护,可移植。 可测试 软件黑盒测试更普遍,但很难覆盖所有应用场景。于是有了接口测试、模块化测试以及单元测试。都是通过降低测试对象