其他分享
首页 > 其他分享> > Tomcat参数优化

Tomcat参数优化

作者:互联网

image-20210622154519229

从这个图中可以得出,限制Tomcat请求数量的因素四个方面。

当前服务器系统资源

我想可能大家遇到过类似“Socket/File:Can't open so many files”的异常,这个就是表示Linux系统中的文件句柄限制。

在Linux中,每一个TCP连接会占用一个文件描述符(fd),一旦文件描述符超过Linux系统当前的限制,就会提示这个错误。

我们可以通过下面这条命令来查看一个进程可以打开的文件数量

ulimit -a 或者 ulimit -n

open files (-n) 1024 是linux操作系统对一个进程打开的文件句柄数量的限制(也包含打开的套接字数量)

这里只是对用户级别的限制,其实还有个是对系统的总限制,查看系统总线制:

cat /proc/sys/fs/file-max

file-max是设置系统所有进程一共可以打开的文件数量 。同时一些程序可以通过setrlimit调用,设置每个进程的限制。如果得到大量使用完文件句柄的错误信息,是应该增加这个值。

当出现上述异常时,我们可以通过下面的方式来进行修改(针对单个进程的打开数量限制)

vi /etc/security/limits.conf
  root soft nofile 65535
  root hard nofile 65535
  * soft nofile 65535
  * hard nofile 65535

另外还要注意,要确保针对进程级别的文件打开数量反问是小于或者等于系统的总限制,否则,我们需要修改系统的总限制。

vi /proc/sys/fs/file-max

TCP连接对于系统资源最大的开销就是内存。

因为tcp连接归根结底需要双方接收和发送数据,那么就需要一个读缓冲区和写缓冲区,这两个buffer在linux下最小为4096字节,可通过cat /proc/sys/net/ipv4/tcp_rmem和cat /proc/sys/net/ipv4/tcp_wmem来查看。

所以,一个tcp连接最小占用内存为4096+4096 = 8k,那么对于一个8G内存的机器,在不考虑其他限制下,最多支持的并发量为:810241024/8 约等于100万。此数字为纯理论上限数值,在实际中,由于linux kernel对一些资源的限制,加上程序的业务处理,所以,8G内存是很难达到100万连接的,当然,我们也可以通过增加内存的方式增加并发量。

Tomcat依赖的JVM的配置

我们知道Tomcat是Java程序,运行在JVM上,因此我们还需要对JVM做优化,才能更好的提升Tomcat的性能,简单带大家了解一下JVM,如下图所示。

image-20210623204411021

在JVM中,内存划分为堆、程序计数器、本地方发栈、方法区(元空间)、虚拟机栈。

堆空间说明

其中,堆内存是JVM内存中最大的一块区域,几乎所有的对象和数组都会被分配到堆内存中,它被所有线程共享。 堆空间被划分为新生代和老年代,新生代进一步划分为Eden和Surivor区,如下图所示。

image-20210623205840226

新生代和老年代的比例是1:2,也就是新生代会占1/3的堆空间,老年代会占2/3的堆空间。 另外,在新生代中,空间占比为Eden:Surivor0:Surivor1=8:1:1 。 举个例子来说,如果eden区内存大小是40M,那么两个Survivor区分别是占5M,整个新生代就是50M,然后计算出老年代的内存大小是100M,也就是说堆空间的总内存大小是150M。

可以通过 java -XX:PrintFlagsFinal -version查看默认参数

uintx InitialSurvivorRatio                      = 8
uintx NewRatio                                  = 2

InitialSurvivorRatio: 新生代Eden/Survivor空间的初始比例

NewRatio : Old区/Young区的内存比例

堆内存的具体工作原理是:

GC标记-清除算法 在执行过程中暂停其他线程??

image-20210623214030533

程序计数器

程序计数器是用来记录各个线程执行的字节码地址等,当线程发生上下文切换时,需要依靠这个来记住当前执行的位置,当下次恢复执行后要沿着上一次执行的位置继续执行。

方法区

方法区是逻辑上的概念,在HotSpot虚拟机的1.8版本中,它的具体实现就是元空间。

方法区主要用来存放已经被虚拟机加载的类相关信息,包括类元信息、运行时常量池、字符串常量池,类信息又包括类的版本、字段、方法、接口和父类信息等。

方法区和堆空间类似,它是一个共享内存区域,所以方法区是属于线程共享的。

本地方发栈和虚拟机栈

Java虚拟机栈是线程私有的内存空间,当创建一个线程时,会在虚拟机中申请一个线程栈,用来保存方法的局部变量、操作数栈、动态链接方法等信息。每一个方法的调用都伴随这栈帧的入栈操作,当一个方法返回之后,就是栈帧的出栈操作。

本地方法栈和虚拟机栈类似,本地方法栈是用来管理本地方法的调用,也就是native方法。

JVM内存应该怎么设置

了解了上述基本信息之后,那么JVM中内存应该如何设置呢?有哪些参数来设置?

而在JVM中,要配置的几个核心参数无非是。

JVM内存的大小,取决于机器的配置,比如一个2核4G的服务器,能够分配给JVM进程也就2G左右,因为机器本身也需要内存,而且机器上还运行了其他的进程也需要占内存。而这2G还得分配给栈内存、堆内存、元空间,那堆内存能够得到的也就1G左右,然后堆内存还要分新生代、老年代。

Tomcat本身的配置

http://tomcat.apache.org/tomcat-8.0-doc/config/http.html

The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool. Note that if an executor is configured any value set for this attribute will be recorded correctly but it will be reported (e.g. via JMX) as -1 to make clear that it is not used.

server:
  tomcat:
    uri-encoding: UTF-8
    #最大工作线程数,默认200, 4核8g内存,线程数经验值800
    #操作系统做线程之间的切换调度是有系统开销的,所以不是越多越好。
    max-threads: 1000
    # 等待队列长度,默认100,
    accept-count: 1000
    max-connections: 20000
    # 最小工作空闲线程数,默认10, 适当增大一些,以便应对突然增长的访问量
    min-spare-threads: 100

标签:Eden,Tomcat,tomcat,新生代,线程,内存,JVM,参数,优化
来源: https://www.cnblogs.com/xiaoyuxixi/p/15425688.html