100万并发连接服务器笔记之java netty处理1m连接会怎么样 -凯发k8网页登录

记录工作/学习的点点滴滴。

100万并发连接服务器笔记之java netty处理1m连接会怎么样

前言

每一种该语言在某些极限情况下的表现一般都不太一样,那么我常用的java语言,在达到100万个并发连接情况下,会怎么样呢,有些好奇,更有些期盼。
这次使用经常使用的顺手的 nio框架(netty-3.6.5.final),封装的很好,接口很全面,就像它现在的域名 netty.io,专注于网络io。
整个过程没有什么技术含量,浅显分析过就更显得有些枯燥无聊,准备好,硬着头皮吧。

测试服务器配置

运行在vmware workstation 9中,64位centos 6.2系统,分配14.9g内存左右,4核。
已安装有java7版本:

java version "1.7.0_21"
java(tm) se runtime environment (build 1.7.0_21-b11)
java hotspot(tm) 64-bit server vm (build 23.21-b01, mixed mode)

在/etc/sysctl.conf中添加如下配置:

fs.file-max = 1048576
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_mem = 786432 2097152 3145728
net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

在/etc/security/limits.conf中添加如下配置:

     *	soft nofile 1048576
     *	hard nofile 1048576

测试端

测试端无论是配置还是程序和以前一样,翻看前几篇博客就可以看到client5.c的源码,以及相关的配置信息等。

服务器程序

这次也是很简单呐,没有业务功能,客户端http请求,服务端输出chunked编码内容。

入口httpchunkedserver.java:

唯一的自定义处理器httpchunkedserverhandler.java:

启动脚本start.sh

达到100万并发连接时的一些信息

每次服务器端达到一百万个并发持久连接之后,然后关掉测试端程序,断开所有的连接,等到服务器端日志输出在线用户为0时,再次重复以上步骤。在这反反复复的情况下,观察内存等信息的一些情况。以某次断开所有测试端为例后,当前系统占用为(设置为list_free_1):

                  total       used       free     shared    buffers     cached
     mem:         15189       7736       7453          0         18        120
     -/  buffers/cache:       7597       7592
     swap:         4095        948       3147

通过top观察,其进程相关信息

    pid user      pr  ni  virt  res  shr s %cpu %mem    time   command                                                                                       
   4925 root      20   0 8206m 4.3g 2776 s  0.3 28.8  50:18.66 java

在启动脚本start.sh中,我们设置堆内存为6g。

ps aux|grep java命令获得信息:

  root      4925 38.0 28.8 8403444 4484764 ?     sl   15:26  50:18 java -server...httpchunkedserver 8000

rss占用内存为4484764k/1024k=4379m

然后再次启动测试端,在服务器接收到online user 1023749时,ps aux|grep java内容为:

  root      4925 43.6 28.4 8403444 4422824 ?     sl   15:26  62:53 java -server...

查看当前网络信息统计

  ss -s
  total: 1024050 (kernel 1024084)
  tcp:   1023769 (estab 1023754, closed 2, orphaned 0, synrecv 0, timewait 0/0), ports 12
  transport total     ip        ipv6
  *    1024084   -         -        
  raw     0         0         0        
  udp     7         6         1        
  tcp     1023767   12        1023755  
  inet    1023774   18        1023756  
  frag    0         0         0    

通过top查看一下

  top -p 4925
  top - 17:51:30 up  3:02,  4 users,  load average: 1.03, 1.80, 1.19
  tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
  cpu0  :  0.9%us,  2.6%sy,  0.0%ni, 52.9%id,  1.0%wa, 13.6%hi, 29.0%si,  0.0%st
  cpu1  :  1.4%us,  4.5%sy,  0.0%ni, 80.1%id,  1.9%wa,  0.0%hi, 12.0%si,  0.0%st
  cpu2  :  1.5%us,  4.4%sy,  0.0%ni, 80.5%id,  4.3%wa,  0.0%hi,  9.3%si,  0.0%st
  cpu3  :  1.9%us,  4.4%sy,  0.0%ni, 84.4%id,  3.2%wa,  0.0%hi,  6.2%si,  0.0%st
  mem:  15554336k total, 15268728k used,   285608k free,     3904k buffers
  swap:  4194296k total,  1082592k used,  3111704k free,    37968k cached
    pid user      pr  ni  virt  res  shr s %cpu %mem    time   command                                                                                       
   4925 root      20   0 8206m 4.2g 2220 s  3.3 28.4  62:53.66 java

四核都被占用了,每一个核心不太平均。这是在虚拟机中得到结果,可能真实服务器会更好一些。 因为不是cpu密集型应用,cpu不是问题,无须多加关注。

系统内存状况

  free -m
               total       used       free     shared    buffers     cached
  mem:         15189      14926        263          0          5         56
  -/  buffers/cache:      14864        324
  swap:         4095       1057       3038

物理内存已经无法满足要求了,占用了1057m虚拟内存。

查看一下堆内存情况

  jmap -heap 4925
  attaching to process id 4925, please wait...
  debugger attached successfully.
  server compiler detected.
  jvm version is 23.21-b01
  using parallel threads in the new generation.
  using thread-local object allocation.
  concurrent mark-sweep gc
  heap configuration:
     minheapfreeratio = 40
     maxheapfreeratio = 70
     maxheapsize      = 6442450944 (6144.0mb)
     newsize          = 629145600 (600.0mb)
     maxnewsize       = 629145600 (600.0mb)
     oldsize          = 5439488 (5.1875mb)
     newratio         = 2
     survivorratio    = 1
     permsize         = 52428800 (50.0mb)
     maxpermsize      = 52428800 (50.0mb)
     g1heapregionsize = 0 (0.0mb)
  heap usage:
  new generation (eden   1 survivor space):
     capacity = 419430400 (400.0mb)
     used     = 308798864 (294.49354553222656mb)
     free     = 110631536 (105.50645446777344mb)
     73.62338638305664% used
  eden space:
     capacity = 209715200 (200.0mb)
     used     = 103375232 (98.5863037109375mb)
     free     = 106339968 (101.4136962890625mb)
     49.29315185546875% used
  from space:
     capacity = 209715200 (200.0mb)
     used     = 205423632 (195.90724182128906mb)
     free     = 4291568 (4.0927581787109375mb)
     97.95362091064453% used
  to space:
     capacity = 209715200 (200.0mb)
     used     = 0 (0.0mb)
     free     = 209715200 (200.0mb)
     0.0% used
  concurrent mark-sweep generation:
     capacity = 5813305344 (5544.0mb)
     used     = 4213515472 (4018.321487426758mb)
     free     = 1599789872 (1525.6785125732422mb)
     72.48054631000646% used
  perm generation:
     capacity = 52428800 (50.0mb)
     used     = 5505696 (5.250640869140625mb)
     free     = 46923104 (44.749359130859375mb)
     10.50128173828125% used
  1439 interned strings occupying 110936 bytes.

老生代占用内存为72%,较为合理,毕竟系统已经处理100万个连接。

再次断开所有测试端,看看系统内存(free -m)

               total       used       free     shared    buffers     cached
  mem:         15189       7723       7466          0         13        120
  -/  buffers/cache:       7589       7599
  swap:         4095        950       3145

记为list_free_2

list_free_1list_free_2两次都释放后的内存比较结果,系统可用物理已经内存已经降到7589m,先前可是7597m物理内存。
总之,我们的java测试程序在内存占用方面已经,最低需要7589 950 = 8.6g内存为最低需求内存吧。

gc日志

我们在启动脚本处设置的一大串参数,到底是否达到目标,还得从gc日志处获得具体效果,推荐使用。

gc事件概览:

其它:
 

总之:

  • 只进行了一次full gc,代价太高,停顿了12秒。
  • partnew成为了停顿大户,导致整个系统停顿了41秒之久,不可接受。
  • 当前jvm调优喜忧参半,还得继续努力等

小结

java与与erlang、c相比,比较麻烦的事情,需要在程序一开始就得准备好它的堆栈到底需要多大空间,换个说法就是jvm启动参数设置堆内存大小,设置合适的垃圾回收机制,若以后程序需要更多内存,需停止程序,编辑启动参数,然后再次启动。总之一句话,就是麻烦。单单jvm的调优,就得持续不断的根据检测、信息、日志等进行适当微调。

  • jvm需要提前指定堆大小,相比erlang/c,这可能是个麻烦
  • gc(垃圾回收),相对比麻烦,需要持续不断的根据日志、jvm堆栈信息、运行时情况进行jvm参数微调
  • 设置一个最大连接目标,多次测试达到顶峰,然后释放所有连接,反复观察内存占用,获得一个较为合适的系统运行内存值
  • eclipse memory analyzer结合jmap导出堆栈dump文件,分析内存泄漏,还是很方便的
  • 想修改运行时内容,或者称之为热加载,默认不可能
  • 真实机器上会有更好的反映

吐槽一下:
java osgi,相对比erlang来说,需要人转换思路,不是那么原生的东西,总是有些别扭,社区或商业公司对此的修修补补,不过是实现一些面向对象所不具备的热加载的企业特性。

测试源代码,。

posted on 2013-05-13 11:16 nieyong 阅读(62362) 评论(9)     所属分类: c1m

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样 2013-05-17 16:17

lz你好,按照你的程序及配置,部署到linux机子上测试,发现online user 大概到300就上不去了,能否指点下问题在哪里,甚是苦恼啊 系统信息为 虚拟机centos6.5 内存8g cpu 4核  回复     

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样 2013-05-19 16:23 nieyong

@小孟
问题太模糊,很难清晰定位。服务器端,需要修改两处:
1. 编辑/etc/security/limits.conf文件,添加如下内容
* soft nofile 1048576
* hard nofile 1048576

2. 在/etc/sysctl.conf中添加如下配置:

fs.file-max = 1048576
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_mem = 786432 2097152 3145728
net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

在测试端,也需要执行两处:
1. 编辑/etc/security/limits.conf文件,添加如下内容

* soft nofile 1048576
* hard nofile 1048576
2. 在/etc/sysctl.conf中添加如下配置:

fs.file-max = 1048576
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_mem = 786432 2097152 3145728
net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

测试端最重要配置也就是
fs.file-max = 1048576
net.ipv4.ip_local_port_range = 1024 65535

具体问题,请具体定位。  回复     

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样 2013-05-20 17:32

@nieyong
谢谢你的回复 我今天重新安装了系统 换成64位centos 发现连接数上去了 看来服务器系统还是非常关键的  回复     

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样 2013-07-12 10:58

java与c,erlang的玩法都不一样,有些比较是片面的  回复     

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样 2013-10-02 15:35

请问100万的并发是用什么工具产生的?一共用了几台压力机?
我的压力机在win平台使用loadrunner模拟1w并发就已经卡的不行了,根本没法跑到100w  回复     

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样 2013-11-21 11:58

请问100万的并发是用什么工具产生的?一共用了几台压力机?您这个压力测试工具是什么?  回复     

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样[未登录] 2013-12-17 13:04

100万并发连接至少要16台客户机才能完全实现!!  回复     

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样[未登录] 2013-12-17 13:09

准确的来说是16块网卡  回复     

# re: 100万并发连接服务器笔记之java netty处理1m连接会怎么样 2014-03-07 21:42 海边沫沫

开启一个java虚拟机,无法避免的问题就是一次full gc时间太长。
如果分成10个java虚拟机,每个只配置1g内存,就不会有full gc太占时间的问题了。  回复     


只有注册用户后才能发表评论。


网站导航:
              
 

公告

所有文章皆为原创,若转载请标明出处,谢谢~

新浪微博,欢迎关注:

导航

2013年5月
2829301234
567891011
121415161718
19202122232425
2627282930311
2345678

统计

常用链接

留言簿(58)

随笔分类(129)

随笔档案(149)

个人收藏

最新随笔

搜索

最新评论

阅读排行榜

评论排行榜

网站地图