21丨Tomcat:中间件监控及常用计数器解析

在当今 Spring Cloud 微服务架构盛行的时代,Tomcat 仍然作为应用最广的应用服务器而存在着,所以我们不得不说一说对它的性能分析。

很多时候,我们做性能测试分析时,都会把 Tomcat 这类的应用弄混淆。对它的监控和分析,总是会和 JDK、框架代码、业务代码混合来看,这就导致了分析上的混乱。我们应该把这些分析内容分隔开来,哪些是 tomcat,哪些是 JDK 等。

在我看来,Tomcat、WebLogic、WebSphere、JBoss 等,它们都具有同样的分析思路。因为 Tomcat 的市场范围更大,所以,今天,我们以它为例来说明这类应用应该如何分析。

首先我们得知道它的架构是什么样的。

img

这是一个在网上随处可见的架构图,它能告诉我们 Tomcat 内部如何运作。如果你有兴趣,还可以看一下官方对它的架构描述。

然而,我们做性能分析的人真的要完全掌握这些细节吗?当然不是。从经验上来说,基本上有几大方面,是 Tomcat 优化时需要关注的。

如下图所示:

img

最上面,我放了两个框,分别是操作系统和 JDK。因为要调优 Tomcat,和这两者非常相关,但是操作系统和 JDK 又各自有独立的分析逻辑,而在本篇中,我专门讲 Tomcat 类型的组件,所以上面两块的内容我将尽量不涉及,以免混乱。

在 Tomcat 的性能分析中,我将我认为重要的几个技术点列在了思维导图中,同时也对它们做了重要程度的标识。在我分析经验中,这些内容已经包括了大部分的优化场景。

运行模式之争

有很多人对运行模式非常敏感,大家也看到经常有文章说:“对于性能来说,显然是 BIO<NIO<APR 的。”然而也有人做过测试说,其实不见得 BIO 性能就最差,这取决于应用场景;也有人说在压力低的情况下,显然 BIO 的性能更高。

从我的经验上来说,真的没必要纠结这一点。本着对 Tomcat 官方的信任,我觉得最好就是用官方给的默认运行模式,它肯定是经过了更严格的测试才被选择的。这就跟相信世上好人多是一样的道理。

现在新的 Tomcat 版本中默认的是 NIO 了,你可以在启动日志中看到相应的信息,如下所示:

21-Jan-2020 16:50:57.989 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-jsse-nio-443"]

简单地说 BIO 和 NIO 的区别如下面两张图所示。

BIO 图示:

img

NIO 图示:

img

要理解这个区别,首先得知道几个知识点:

  1. Acceptor 是 TCP 层面的东西,它负责完成 TCP 握手的过程,放入全连接队列,然后将数据生成 request,调用servlet 容器处理。

  2. 而 Worker 干的就是接到 request 数据,处理后给出 response。

  3. Poller 是一个队列,属于典型的生产者 - 消费者模式。

知道了这些,你就会明白其实对于 Acceptor 和 Worker 本身来说,仍然是阻塞的。而这个 Poller 只能是在大并发的时候,可以 hold 住更多的请求而已,看起来 Tomcat 处理请求的容量增加了,但是我们还是要在具体的应用中去测试,来比对响应时间的差异。

但是还有一点区别我们得知道,Tomcat 的 keepAliveTimeout 参数默认使用的是 connectionTimeout 的值。这样一来,由于使用 BIO 时,Acceptor 读取 socket 中的数据并传递给 Worker 这个过程是阻塞的,意味着当代码执行到 Worker 中时,这个 socket 仍然被占着;而使用 NIO 时,Acceptor 读取 socket 数据后交给了 Poller 了,Worker 从 Poller 中得到请求内容并处理,这个过程就分开了,这样 Worker 在处理时就不会阻塞 socket,所以 Tomcat 可以处理更多的 socket,这才是 NIO 性能提升的关键点。

而 APR 是个啥呢?它是利用了 OS 中的能力来进行高并发地文件读取或者网络传输,来提高对静态文件的处理。有很多网上的实验结果都可以证明,在具体的应用中它并没有比 NIO 的性能高到哪里去,并且配置起来还麻烦,所以这个模式现在并没有很广泛的使用。

所以在 Tomcat 中,运行模式之争应该说已经不存在了。

请求量、请求时间、响应时间

这是我希望你能在分析 Tomcat 时关注的内容。我们有很多种方式可以看这些信息,最简单的就是访问日志了。通过在 conf/server.xml 中做如下配置:


<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
             prefix="localhost_access_log" suffix=".txt"
             pattern="%h %l %u %t &quot;%r&quot; %s %b %D %F" />

其中 %D 就是请求时间,%F 是响应时间。配置了之后,在日志中就会看到如下内容:

172.17.211.144 - - [21/Jan/2020:18:06:57 +0800] "POST /back/save HTTP/1.1" 200 14 29 29
172.17.211.144 - - [21/Jan/2020:18:06:57 +0800] "GET /validate/code/pic HTTP/1.1" 200 541 5 0

最后两列就是请求时间和响应时间。通过这两个时间的比对,你就可以知道,Tomcat 本身消耗了多少时间以及 Tomcat 之后的操作又消耗了多少时间。

当然,如果你喜欢的话,也可以看这样的监控图表。

img

这是一个小工具 Probe 的监控数据,从这里,你可以知道 Tomcat 这段时间处理了多少请求,以及处理这些请求的时间、最大时间、最小时间和平均时间。

但是!我不建议用这个工具来监控 Tomcat,因为它性能差。你可能会问,那你还说它干吗?因为其他的性能监控工具中,很少有见到这个角度的图表展示,在这里只是为了告诉你,分析 Tomcat 全局性能状态时,可以通过总请求数,以及平均响应时间来看 Tomcat 的全局处理能力如何。

当然这些数据你同样可以通过分析访问日志获取。

显然有了这些数据,我们就可以做一个大体的判断了。在服务节点多的时候,只要看这里的平均响应时间,你就能知道在这个 Tomcat 上有没有消耗掉你在压力工具中看到的响应时间。

下面我通过测试结果来说明几个 Tomcat 中常用的优化动作。

在展示优化动作之前,先看一下 connector 基本配置:


<Connector
    SSLEnabled="true"
    acceptCount="100"
    clientAuth="false"
    disableUploadTimeout="true"
    enableLookups="false"
    maxThreads="25"
    port="443"
    connectionTimeout="20000"
    keystoreFile="/PathToTomcat/bin/server.keystore"
    keystorePass="12345678"
    protocol="org.apache.coyote.http11.Http11NioProtocol"
    scheme="https"
    secure="true"
    sslProtocol="TLS" />

这只是一个基本配置。至于是不是最优的配置,我们需要在针对一个应用测试的过程中慢慢来看。

比如有人会说,你这里为什么不配置 minSpareThreads 和 maxSpareThreads 之类的参数?首先,我们要知道,为什么要配置这两个参数?对于一个线程数超高的应用来说,长期维护大量的线程肯定会导致操作系统中 context switch 的增加,在一个应用的波峰波谷差别较大的时候,我们用这两个参数其实是为了减少在波谷时产生的维护成本。但是同时你也要知道,在线程不够用的时候,开新的线程也同样需要成本,所以这两个值需不需要配置,完全取决于应用场景的具体测试结果。

总之,所有的配置都需要在具体的应用场景测试了之后,再下定论,别凭感觉。

协议 HTTP、HTTPS

我们知道在 HTTPS 的协议中,因为加入了 SSL 证书会导致性能下降,但是对有些应用来说,又不得不用 SSL 证书。在这里我自己配置了一个证书,来给你看看证书对性能产生的影响。

img

我的证书配置是这样的:

  • 根证书:RSA 证书、sha256,8192 位

  • 中级证书:RSA,sha256、4096 位

  • 终端证书:RSA,sha256、4096 位

一般情况下,SSL 证书都是分为三层的。在这个例子中,我生成的时候还特意用了高位数,位数越高,对性能影响越大,因为计算成本增加了。现在我们在市场上买的证书,根据价值的不同,加密方式和位数都会不一样,请稍微注意一下。

下面来看看测试结果。

Tomcat with SSL:


summary +    588 in 00:00:13 =   46.0/s Avg:    10 Min:     1 Max:   804 Err:     0 (0.00%) Active: 1 Started: 1 Finished: 0
summary +   4403 in 00:00:30 =  146.8/s Avg:     4 Min:     0 Max:    87 Err:     0 (0.00%) Active: 2 Started: 2 Finished: 0
summary =   4991 in 00:00:43 =  116.7/s Avg:     5 Min:     0 Max:   804 Err:     0 (0.00%)
summary +   7107 in 00:00:30 =  237.1/s Avg:     4 Min:     0 Max:    77 Err:     0 (0.00%) Active: 3 Started: 3 Finished: 0
summary =  12098 in 00:01:13 =  166.3/s Avg:     5 Min:     0 Max:   804 Err:     0 (0.00%)
summary +  11121 in 00:00:30 =  370.7/s Avg:     4 Min:     0 Max:    72 Err:     0 (0.00%) Active: 4 Started: 4 Finished: 0
summary =  23219 in 00:01:43 =  226.0/s Avg:     4 Min:     0 Max:   804 Err:     0 (0.00%)
summary +  12709 in 00:00:30 =  423.6/s Avg:     4 Min:     0 Max:    87 Err:     0 (0.00%) Active: 5 Started: 5 Finished: 0
summary =  35928 in 00:02:13 =  270.6/s Avg:     4 Min:     0 Max:   804 Err:     0 (0.00%)
summary +  14548 in 00:00:30 =  485.0/s Avg:     4 Min:     0 Max:    69 Err:     0 (0.00%) Active: 6 Started: 6 Finished: 0
summary =  50476 in 00:02:43 =  310.1/s Avg:     4 Min:     0 Max:   804 Err:     0 (0.00%)
summary +  15810 in 00:00:30 =  527.0/s Avg:     5 Min:     0 Max:    83 Err:     0 (0.00%) Active: 7 Started: 7 Finished: 0
summary =  66286 in 00:03:13 =  343.9/s Avg:     4 Min:     0 Max:   804 Err:     0 (0.00%)
summary +  15242 in 00:00:30 =  508.0/s Avg:     5 Min:     0 Max:    77 Err:     0 (0.00%) Active: 8 Started: 8 Finished: 0
summary =  81528 in 00:03:43 =  366.0/s Avg:     4 Min:     0 Max:   804 Err:     0 (0.00%)
summary +  16709 in 00:00:30 =  557.1/s Avg:     5 Min:     0 Max:    75 Err:     0 (0.00%) Active: 9 Started: 9 Finished: 0
summary =  98237 in 00:04:13 =  388.7/s Avg:     5 Min:     0 Max:   804 Err:     0 (0.00%)
summary +  17099 in 00:00:30 =  570.0/s Avg:     6 Min:     0 Max:   161 Err:     0 (0.00%) Active: 10 Started: 10 Finished: 0
summary = 115336 in 00:04:43 =  407.9/s Avg:     5 Min:     0 Max:   804 Err:     0 (0.00%)

Tomcat without SSL:


summary +     12 in 00:00:03 =    4.2/s Avg:   148 Min:     4 Max:   937 Err:     0 (0.00%) Active: 1 Started: 1 Finished: 0
summary +   3531 in 00:00:30 =  117.8/s Avg:     4 Min:     0 Max:    63 Err:     0 (0.00%) Active: 2 Started: 2 Finished: 0
summary =   3543 in 00:00:33 =  107.8/s Avg:     4 Min:     0 Max:   937 Err:     0 (0.00%)
summary +   7283 in 00:00:30 =  242.8/s Avg:     4 Min:     0 Max:    90 Err:     0 (0.00%) Active: 3 Started: 3 Finished: 0
summary =  10826 in 00:01:03 =  172.2/s Avg:     4 Min:     0 Max:   937 Err:     0 (0.00%)
summary +   9554 in 00:00:30 =  318.5/s Avg:     3 Min:     0 Max:    35 Err:     0 (0.00%) Active: 4 Started: 4 Finished: 0
summary =  20380 in 00:01:33 =  219.5/s Avg:     4 Min:     0 Max:   937 Err:     0 (0.00%)
summary +  14747 in 00:00:30 =  491.6/s Avg:     3 Min:     0 Max:    49 Err:     0 (0.00%) Active: 5 Started: 5 Finished: 0
summary =  35127 in 00:02:03 =  285.9/s Avg:     3 Min:     0 Max:   937 Err:     0 (0.00%)
summary +  16844 in 00:00:30 =  561.4/s Avg:     3 Min:     0 Max:    47 Err:     0 (0.00%) Active: 6 Started: 6 Finished: 0
summary =  51971 in 00:02:33 =  340.0/s Avg:     3 Min:     0 Max:   937 Err:     0 (0.00%)
summary +  17547 in 00:00:30 =  585.0/s Avg:     3 Min:     0 Max:    47 Err:     0 (0.00%) Active: 7 Started: 7 Finished: 0
summary =  69518 in 00:03:03 =  380.2/s Avg:     3 Min:     0 Max:   937 Err:     0 (0.00%)
summary +  18798 in 00:00:30 =  626.6/s Avg:     4 Min:     0 Max:   213 Err:     0 (0.00%) Active: 8 Started: 8 Finished: 0
summary =  88316 in 00:03:33 =  414.9/s Avg:     3 Min:     0 Max:   937 Err:     0 (0.00%)
summary +  18529 in 00:00:30 =  617.6/s Avg:     4 Min:     0 Max:   204 Err:     0 (0.00%) Active: 9 Started: 9 Finished: 0
summary = 106845 in 00:04:03 =  439.9/s Avg:     3 Min:     0 Max:   937 Err:     0 (0.00%)
summary +  18837 in 00:00:30 =  627.9/s Avg:     4 Min:     0 Max:    53 Err:     0 (0.00%) Active: 10 Started: 10 Finished: 0
summary = 125682 in 00:04:33 =  460.6/s Avg:     4 Min:     0 Max:   937 Err:     0 (0.00%)

这里稍微啰嗦一下,我们以这种终端直接输出的数据看 JMeter 的结果时,主要关注下"summary +"的数据,因为"summary ="的数据是整个场景执行的平均数据。另外,第一行的数据会不准确,可以忽略,如果你把粒度调低一些,可以看到更细的数据。

通过上面的数据可以看到,没有 SSL 比有 SSL 证书是要高出一些 TPS 的。如下图所示:

img

显然 SSL 证书对性能有明显的影响了,最大的影响到 18.93%,是在 8 个线程时,而在五六个线程时,TPS 损耗有 13% 左右。

这和加密位数、应用场景等都有关系,所以这一段可以给你的结论就是:SSL 证书对性能会有损耗。但具体损耗是多少,在你的应用场景中需要具体测试。

线程池

Tomcat 的线程池,一直是调优 Tomcat 的重点对象。在我的工作经验中,我发现经常有人不太清楚对 Tomcat 应该配置多大的线程池。

之前,我见过有一个人在一个 4C8G 的机器上把一个 Tomcat 节点的线程池配置到了 4000。我问他为什么要这么配置,他说想支持 4000 的并发用户。

我们先不说他有没有理解在线用户、并发用户和 TPS 之间的逻辑关系,只说把 Tomcat 配置为 4000 这个事情。就算 Tomcat 能支撑得住 4000,但机器能撑得住吗?结果还没跑多少压力线程,操作系统的 CS 就不断走高,消耗了大量的 sy CPU,只有少量的 us CPU 能处理正常的业务。

然后我告诉他把 Tomcat 线程数调到默认的 200 先看看,结果 TPS 上升了好几倍。

这就是对线程在系统中运行的逻辑不理解导致的情况。

我们在测试的时候,先得学会判断:线程数到底够不够用。要是不够用,但又有足够的硬件资源,那你可以增加线程。<

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值