`
m635674608
  • 浏览: 5041505 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

100万并发连接服务器笔记之Java Netty处理1M连接会怎么样

    博客分类:
  • java
 
阅读更多

前言

每一种该语言在某些极限情况下的表现一般都不太一样,那么我常用的Java语言,在达到100万个并发连接情况下,会怎么样呢,有些好奇,更有些期盼。  
这次使用经常使用的顺手的     netty 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)

 

测试端

测试端和以前一样的程序,翻看前几篇博客就可以看到client5.c的源码。

在/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

 

服务器程序

这次也是很简单呐,没有业务功能,客户端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_1和  list_free_2两次都释放后的内存比较结果,系统可用物理已经内存已经降到7589M,先前可是7597M物理内存。  
总之,我们的JAVA测试程序在内存占用方面已经,最低需要7589 + 950 = 8.6G内存为最低需求内存吧。

GC日志

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

GC事件概览:  
    gc_eventdetails

其它:  
    gc_total_1      gc_total_2     gc_total_3

总之:

  • 只进行了一次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来说,需要人转换思路,不是那么原生的东西,总是有些别扭,社区或商业公司对此的修修补补,不过是实现一些面向对象所不具备的热加载的企业特性。

测试源代码,  下载just_test

 

http://m.oschina.net/blog/479373
分享到:
评论

相关推荐

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

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

    c++客户端和java(Netty)服务器端tcp通讯

    利用Netty,我们可以轻松实现TCP服务器,创建ServerBootstrap,配置通道处理器pipeline,监听客户端连接,并处理接收到的数据。 Netty中的ChannelHandlerContext类是事件处理的核心,它提供了发送和接收数据的方法...

    Java + Netty 实现的高并发高可用MQTT服务broker,轻松支持10万并发,已用于生产环境

    Java + Netty 实现的高并发高可用MQTT服务broker,轻松支持10万并发,已用于生产环境 技术体系:(使用 netty 实现通信及协议解析,使用 nutzboot 提供依赖注入及属性配置,使用 redis 实现消息缓存,集群,使用 ...

    基于Netty的Java数据采集软件

    其非阻塞I/O模型使得Netty能处理大量并发连接,这对于数据采集这样需要与多个数据源频繁交互的任务而言,无疑是理想的选择。 在这个基于Netty的Java数据采集软件中,"DataServer"模块扮演了核心角色,它是数据接收...

    Java采用Netty实现基于DTU的TCP服务器 + 多端口 + 多协议

    本文将深入探讨如何使用Java的Netty框架实现一个基于DTU(Data Transfer Unit)的TCP服务器,该服务器具备多端口通信和多协议解析的能力。 首先,DTU是一种专门用于远程数据传输的设备,它能够通过GPRS、3G/4G等...

    JavaNetty客户端与服务器

    标题"Java Netty客户端与服务器"表明我们将探讨如何使用Netty构建一个简单的服务器和客户端系统,其中客户端能够发送消息到服务器,而服务器则会给予响应。这种通信模式在许多分布式系统中非常常见,例如聊天应用、...

    netty-4.1_javaNetty_netty_服务器_

    Netty 是一个基于 Java 的高性能、异步事件驱动的网络应用程序框架,专为开发协议服务器和客户端而设计。它的核心是基于 NIO(非阻塞 I/O)模型,提供了丰富的 API 和高度可定制的组件,使得开发者能够快速、高效地...

    基于Netty消息框架的Java游戏服务器.zip

    当客户端连接到服务器时,Netty会自动创建一个新的Channel实例来处理该连接。服务器通过ChannelHandlerContext与客户端进行交互,可以发送和接收消息。 在性能优化方面,Netty提供了零拷贝特性,减少了内存复制带来...

    java物联网的netty服务器

    Java物联网的Netty服务器是一种基于Java的高性能网络应用框架,主要应用于开发高并发、低延迟的网络服务。Netty由JBOSS组织开发并维护,是Java生态系统中的一个强大工具,广泛用于物联网(IoT)场景,如设备通信、数据...

    JAVA netty 获取串口数据并且下发数据

    总的来说,使用Java Netty进行串口通信提供了一种灵活且高效的方式,尤其在需要处理大量并发连接和数据传输的环境中。通过理解Netty的事件驱动模型和管道机制,我们可以构建出强大的串口应用,例如在题目中提到的,...

    Java + Netty 实现的高并发高可用MQTT服务broker

    Java + Netty 实现的高并发高可用MQTT服务broker,轻松支持10万并发(有群友实现了130万在线)。使用 netty 实现通信及协议解析,使用 nutzboot 提供依赖注入及属性配置,使用 redis 实现消息缓存,集群,使用 kafka ...

    基于netty实现的支持长连接的rpc

    Netty是一个高性能、异步事件驱动的网络应用程序框架,适用于开发高并发、低延迟的网络应用,如服务器和客户端。 在描述中,我们看到了一个简单的使用步骤: 1. 首先,你需要将这个项目作为一个Maven工程导入到...

    Netty 高并发深入浅出学习高并发服务器

    通过深入学习 Netty,开发者可以构建出高效、稳定的高并发服务器,实现复杂网络应用的需求。《深入浅出Netty.pdf》这本书很可能会详细讲解这些知识点,包括理论基础、实践示例以及高级特性的使用,对于理解和掌握 ...

    读书笔记:基于Java Netty 实现的多人联机游戏多人对战的客户端和服务器端.zip

    读书笔记:基于Java Netty 实现的多人联机游戏多人对战的客户端和服务器端

    Netty实现Java服务端和C#客户端联通

    在Java服务端,开发者可以利用Netty构建出稳定且高效的网络服务器,处理来自客户端的连接请求。 C#客户端这边,DotNetty是.NET平台上的一个类似Netty的框架,它允许C#开发者创建基于TCP、UDP、HTTP、WebSocket等...

    基于java netty的udp客户端声呐数据对接

    在"基于Java Netty的UDP客户端声呐数据对接"项目中,我们主要关注如何利用Netty处理UDP通信,以及如何解析和封装SCANFISH-II型声呐系统的数据。 UDP(User Datagram Protocol)是一种无连接的传输层协议,它不保证...

    java netty权威指南完整版带目录

    Java Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这本书“Java Netty权威指南”是深入理解并掌握Netty的关键资源,包含详细的目录,使得学习和查阅更为...

    java应用netty服务端和客户端

    Java应用程序中的Netty框架是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。Netty广泛应用于分布式系统、云计算、大数据处理等领域,它的核心特性包括非阻塞I/O、...

    netty+4G DTU

    Netty 的异步事件驱动模型非常适合处理大量的并发连接,这对于 IoT 应用场景中的海量设备连接至关重要。其非阻塞 I/O 模型可以有效地减少 CPU 资源的消耗,提高系统的整体性能。 在实际应用中,Java 开发者可以利用...

Global site tag (gtag.js) - Google Analytics