定位 Tomcat 中的慢请求(slow request),通常需要从 应用层、Tomcat 层、系统层 三个维度入手。下面是一套比较实用的排查思路和工具清单。
先确认慢请求的特征:
conf/server.xml 中启用 AccessLog:
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b %D" />
重点字段:
%D:请求处理时间(毫秒)%r:请求行%t:时间Example:
192.168.1.10 - - [10/Oct/2024:10:00:00] "GET /api/test HTTP/1.1" 200 1234 1523
→ 这个请求花了 1523ms
查看 conf/server.xml 的 Connector:
<Connector port="8080"
protocol="HTTP/1.1"
maxThreads="200"
acceptCount="100"
connectionTimeout="20000" />
关注:
maxThreads 是否打满connectionTimeout 是否过小或过大-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
用 JConsole / VisualVM 看:
使用 Arthas(强烈推荐)
trace com.xxx.controller.OrderController queryOrder
可以看到:
slow_query_log = 1
long_query_time = 1
trace com.xxx.mapper.OrderMapper selectByExample
查看 GC 日志:
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:gc.log
重点看:
可用:
tcpdumpnginx 日志对比./profiler.sh -d 30 -f flamegraph.html <pid>
能直观看到:
jstack <pid> > thread.txt
看:
BLOCKEDWAITING| 原因 | 表现 |
|---|---|
| 线程池满 | 请求排队 |
| 慢 SQL | 单接口慢 |
| 同步阻塞 | 线程 WAITING |
| GC 频繁 | 偶发全慢 |
| 外部接口慢 | 第三方调用慢 |
| 日志过多 | IO 阻塞 |
trace 定位方法如果你愿意,可以告诉我:
我可以给你更具体的命令和配置示例。