我们有一个 Web 应用程序,它使用在 Java 8 JAX-RS 中开发的 REST 服务和部署在 Apache tomcat 9 上的 WAR。最近我们在生产中遇到了一个问题,即 Tomcat 在高流量下响应非常慢,并且偶尔也会断开连接。所以我们决定运行一些负载测试来确定我们系统的吞吐量。
我们在生产中使用以下规格 -
- 带有 64 位 JVM 的 ubuntu 18.04 Open JDK
- 16 核 CPU 和 64 GB RAM
- 雄猫 9
我们的 Tomcat 服务器 XML 配置是 -
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="300" minSpareThreads="50" acceptCount="250" acceptorThreadCount="2" enableLookups="false" SSLEnabled="true" scheme="https" secure="true"
keystoreFile="/certficate/file/path.jks"
keystorePass="password"
clientAuth="false" sslProtocol="TLS" />
我们有一个 REST API,它是一个简单的“ping”方法,它返回一个简单的 JSON 响应,带有 200。例如
@GET
@Path("/ping")
@Produces(MediaType.APPLICATION_JSON)
public EdoServiceResponse ping() {
return new EdoServiceResponse();
}
{ "status" 200, "responseText" : "OK" }
我们使用它来使用Apache JMeter 5.4.1 执行负载测试。我们的发现:
线程数 | 平均响应时间(毫秒) | 1 分钟内的总请求数 |
---|---|---|
50 | 12 | 243,002 |
100 | 22 | 277,016 |
250 | 40 | 384,729 |
500 | 76 | 400,048 |
1,000 | 124 | 469,712 |
2,000 | 229 | 480,784 |
5,000 | 507 | 336,921 |
10,000 | 1,843 | 74,677 |
正如我们所见,即使负载较小,如 100 或 250 个线程,平均响应时间也开始增加。这是一个简单的 REST API,没有任何数据库连接或逻辑。我们观察到我们的 CPU 使用率从未超过 40%,内存使用率随时保持在 10% 以下。Tomcat 进程永远不会占用超过 4 GB。我们甚至检查了最大打开文件限制,但它设置为 65000,这远高于我们的要求。所以我们无法弄清楚瓶颈在哪里,导致响应时间与没有线程成比例地减少。
我们尝试更改服务器 xml 参数,如 maxThreads、acceptCount、maxConnections 等,但没有显着变化。我们还尝试设置最大堆设置,但没有帮助。只有当我们在 catalina.sh 中添加垃圾收集参数时,我们观察到大约 15-25% 的轻微性能提升的唯一变化是 - -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 -XX:InitiatingHeapOccupancyPercent=70
我们需要弄清楚在 CPU 和内存未充分利用的情况下,我们的系统处理负载的能力是多少,我们不知道为什么即使在 100-200 个线程的低并发情况下它还要花费更多时间来处理请求。我们不知道接下来要采取哪些步骤来提高吞吐量。
任何帮助,将不胜感激。谢谢。