您的位置 首页 java

单机下如何让Java程序支持百万长连接,你知道吗?

单机下能不能让我们的 Java 网络应用支持百万连接?

当然可以!但是有很多的工作要做。

操作系统

首先就是要突破操作系统的限制。

在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个 socket 句柄,每个socket句柄同时也是一个文件句柄)。

可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:

 `$ ulimit -n`

`1024`
  

这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中还得除去每个进程必然打开的标准输入,标准输出等等文件,那么剩下的可用于socket连接的文件数就只有大概1010个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1010个TCP并发连接。

对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量。

修改单个进程打开最大文件数限制的最简单的办法就是使用ulimit命令:

 $ ulimit –n 1000000
  

如果系统回显类似于”Operation not permitted”之类的话,说明上述限制修改失败,实际上是因为在中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。因此,就还需要修改Linux系统对用户的关于打开文件数的软限制和硬限制。

软限制(soft limit):是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;

硬限制(hardlimit):是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。

第一步,修改/etc/security/limits.conf文件,在文件中添加如下行:

   * soft nofile 1000000

  * hard nofile 1000000
  

‘*’号表示修改所有用户的限制;

soft或hard指定要修改软限制还是硬限制;1000000则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。

第二步,修改/etc/pam.d/login文件,在文件中添加如下行:

   session required /lib/security/pam_limits.so 
  

这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。

第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:

   cat /proc/sys/fs/file-max

  12158
  

这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)12158个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。

如何修改这个系统最大文件描述符的限制呢?修改sysctl.conf文件

 vi /etc/sysctl.conf

 # 在末尾添加 

fs.file_max = 1000000

 # 立即生效 

sysctl -p
  

JVM 层面相关性能优化

当客户端的并发连接数达到数十万或者数百万时,系统一个较小的抖动就会导致很严重的后果,例如服务端的GC导致应用暂停。GC持续几秒,就会导致海量的客户端设备掉线或者消息积压,一旦系统恢复,会有海量的设备接入或者海量的数据发送很可能瞬间就把服务端冲垮。

JVM层面的调优主要涉及GC参数优化,GC参数设置不当会导致频繁GC,甚至OOM异常,对服务端的稳定运行产生重大影响。

1.确定GC优化目标

GC(垃圾收集)有三个主要指标。

(1)吞吐量:是评价GC能力的重要指标,在不考虑GC引起的停顿时间或内存消耗时,吞吐量是GC能支撑应用程序达到的最高性能指标。

(2)延迟:GC能力的最重要指标之一,是由于GC引起的停顿时间,优化目标是缩短延迟时间或完全消除停顿(STW),避免应用程序在运行过程中发生抖动。

(3)内存占用:GC正常时占用的内存量。

JVM GC调优的三个基本原则如下。

(1) Minor go回收原则:每次新生代GC回收尽可能多的内存,减少应用程序发生Full GC的频率。

2)GC内存最大化原则:垃圾收集器能够使用的内存越大,垃圾收集效率越高,应用程序运行也越流畅。但是过大的内存一次 Full GC耗时可能较长,如果能够有效避免FullGC,就需要做精细化调优。

(3)3选2原则:吞吐量、延迟和内存占用不能兼得,无法同时做到吞吐量和暂停时间都最优,需要根据业务场景做选择。对于大多数应用,吞吐量优先,其次是延迟。当然对于时延敏感型的业务,需要调整次序。

2.确定服务端内存占用

在优化GC之前,需要确定应用程序的内存占用大小,以便为应用程序设置合适的内存,提升GC效率。内存占用与活跃数据有关,活跃数据指的是应用程序稳定运行时长时间存活的Java对象。活跃数据的计算方式:通过GC日志采集GC数据,获取应用程序稳定时老年代占用的Java堆大小,以及永久代(元数据区)占用的Java堆大小,两者之和就是活跃数据的内存占用大小。

3.GC优化过程

1、GC数据的采集和研读

2、设置合适的JVM堆大小

3、选择合适的垃圾回收器和回收策略

当然具体如何做,请参考JVM相关知识。而且GC调优会是一个需要多次调整的过程,期间不仅有参数的变化,更重要的是需要调整业务代码。

写在最后,如果觉得本文不错! 记得转发+关注一下,后续小编会给大家带来更多原创的精彩技术内容。 也欢迎大家在下方留言,说出你的看法~

文章来源:智云一二三科技

文章标题:单机下如何让Java程序支持百万长连接,你知道吗?

文章地址:https://www.zhihuclub.com/192103.shtml

关于作者: 智云科技

热门文章

网站地图