2)重启 Tomcat,这样 JMX 的监听端口 8011 就开启了,接下来通过 JConsole 来连接这个端口。
首页 > 数据库 > 数据库开发技术 > Tomcat性能调优详解
Tomcat 的关键指标有吞吐量、响应时间、错误数、线程池、CPU 以及 JVM 内存。前三个指标是我们最关心的业务指标,Tomcat 作为服务器,就是要能够又快又好地处理请求,因此吞吐量要大、响应时间要短,并且错误数要少。后面三个指标是跟系统资源有关的,当某个资源出现瓶颈就会影响前面的业务指标,比如线程池中的线程数量不足会影响吞吐量和响应时间;但是线程数太多会耗费大量 CPU,也会影响吞吐量;当内存不足时会触发频繁地 GC,耗费 CPU,最后也会反映到业务指标上来。
JConsole是一款基于JMX的可视化监控和管理工具
1) 开启 JMX 的远程监听端口
我们可以在 Tomcat 的 bin 目录下新建一个名为setenv.sh的文件(或者setenv.bat,根据你的操作系统类型),然后输入下面的内容:
export JAVA_OPTS="${JAVA_OPTS} -Dcom.sun.management.jmxremote"export JAVA_OPTS="${JAVA_OPTS} -Dcom.sun.management.jmxremote.port=8011"export JAVA_OPTS="${JAVA_OPTS} -Djava.rmi.server.hostname=x.x.x.x"export JAVA_OPTS="${JAVA_OPTS} -Dcom.sun.management.jmxremote.ssl=false"export JAVA_OPTS="${JAVA_OPTS} -Dcom.sun.management.jmxremote.authenticate=false"
2)重启 Tomcat,这样 JMX 的监听端口 8011 就开启了,接下来通过 JConsole 来连接这个端口。
jconsole x.x.x.x:8011我们可以看到 JConsole 的主界面:

在 MBeans 标签页下选择 GlobalRequestProcessor,这里有 Tomcat 请求处理的统计信息。你会看到 Tomcat 中的各种连接器,展开“http-nio-8080”,你会看到这个连接器上的统计信息,其中 maxTime 表示最长的响应时间,processingTime 表示平均响应时间,requestCount 表示吞吐量,errorCount 就是错误数。

选择“线程”标签页,可以看到当前 Tomcat 进程中有多少线程,如下图所示:

图的左下方是线程列表,右边是线程的运行栈,这些都是非常有用的信息。如果大量线程阻塞,通过观察线程栈,能看到线程阻塞在哪个函数,有可能是 I/O 等待,或者是死锁。
在主界面可以找到 CPU 使用率指标,请注意这里的 CPU 使用率指的是 Tomcat 进程占用的 CPU,不是主机总的 CPU 使用率。

选择“内存”标签页,你能看到 Tomcat 进程的 JVM 内存使用情况。

极端情况下如果 Web 应用占用过多 CPU 或者内存,又或者程序中发生了死锁,导致 Web 应用对外没有响应,监控系统上看不到数据,这个时候需要我们登陆到目标机器,通过命令行来查看各种指标。
1. 首先我们通过 ps 命令找到 Tomcat 进程,拿到进程 ID。
ps -ef|grep tomcat2. 接着查看进程状态的大致信息,通过cat /proc/

3. 监控进程的 CPU 和内存资源使用情况:

4. 查看 Tomcat 的网络连接,比如 Tomcat 在 8080 端口上监听连接请求,通过下面的命令查看连接列表:

你还可以分别统计处在“已连接”状态和“TIME_WAIT”状态的连接数:

5. 通过 ifstat 来查看网络流量,大致可以看出 Tomcat 当前的请求数和负载状况。

线程池调优指的是给 Tomcat 的线程池设置合适的参数,使得 Tomcat 能够又快又好地处理请求。

<!--namePrefix: 线程前缀maxThreads: 最大线程数,默认设置 200,一般建议在 500 ~ 1000,根据硬件设施和业务来判断minSpareThreads: 核心线程数,默认设置 25prestartminSpareThreads: 在 Tomcat 初始化的时候就初始化核心线程maxQueueSize: 最大的等待队列数,超过则拒绝请求 ,默认 Integer.MAX_VALUEmaxIdleTime: 线程空闲时间,超过该时间,线程会被销毁,单位毫秒className: 线程实现类,默认org.apache.catalina.core.StandardThreadExecutor--><Executor name="tomcatThreadPool" namePrefix="catalina-exec-Fox"prestartminSpareThreads="true"maxThreads="500" minSpareThreads="10" maxIdleTime="10000"/><Connector port="8080" protocol="HTTP/1.1" executor="tomcatThreadPool"connectionTimeout="20000"redirectPort="8443" URIEncoding="UTF-8"/>
这里面最核心的就是如何确定 maxThreads 的值,如果这个参数设置小了,Tomcat 会发生线程饥饿,并且请求的处理会在队列中排队等待,导致响应时间变长;如果 maxThreads 参数值过大,同样也会有问题,因为服务器的 CPU 的核数有限,线程数太多会导致线程在 CPU 上来回切换,耗费大量的切换开销。
理论上我们可以通过公式 线程数 = CPU 核心数 *(1+平均等待时间/平均工作时间),计算出一个理想值,这个值只具有指导意义,因为它受到各种资源的限制,实际场景中,我们需要在理想值的基础上进行压测,来获得最佳线程数。
yml中配置 (属性配置类:ServerProperties)
server:tomcat:threads:min-spare: 20max: 500connection-timeout: 5000ms
SpringBoot中的TomcatConnectorCustomizer类可用于对Connector进行定制化修改。
public class MyTomcatCustomizer implementsWebServerFactoryCustomizer<TomcatServletWebServerFactory> {public void customize(TomcatServletWebServerFactory factory) {factory.setPort(8090);factory.setProtocol("org.apache.coyote.http11.Http11NioProtocol");factory.addConnectorCustomizers(connectorCustomizer());}public TomcatConnectorCustomizer connectorCustomizer(){return new TomcatConnectorCustomizer() {public void customize(Connector connector) {Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();protocol.setMaxThreads(500);protocol.setMinSpareThreads(20);protocol.setConnectionTimeout(5000);}};}}
原文作者:Fox爱分享;如有侵权,请联系管理员删除。