温馨提示×

如何定位tomcat慢请求日志

小樊
45
2026-09-30 17:04:44
栏目: 智能运维

定位 Tomcat 中的慢请求(slow request)日志,可以从日志配置、访问日志、请求耗时统计、线程堆栈等多个层面入手。下面按“由浅入深”的方式说明。


一、开启并分析 Tomcat 访问日志(最基础)

Tomcat 默认使用 AccessLogValve 记录每次请求。

1. 配置访问日志

在 conf/server.xml 中:

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

重点关注:

  • %D:请求处理时间(毫秒)
  • %r:请求行(方法 + URI)
  • %t:时间

示例日志:

127.0.0.1 - - [10/Oct/2024:10:00:00 +0800] "GET /api/list HTTP/1.1" 200 1024 3500

表示 /api/list 耗时 3500ms

2. 筛选慢请求

awk '$NF > 1000' logs/localhost_access_log.*.txt

找出 >1s 的请求。


二、使用 RequestDumper / 自定义 Valve(更细粒度)

1. 使用 RequestDumperValve(调试用)

<Valve className="org.apache.catalina.valves.RequestDumperValve" />

会打印完整请求信息,但性能影响大,不建议生产。


三、通过 Spring / 应用层记录慢请求(推荐)

1. Spring Boot 示例(Interceptor)

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    request.setAttribute("startTime", System.currentTimeMillis());
    return true;
}

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    long cost = System.currentTimeMillis() - (Long) request.getAttribute("startTime");
    if (cost > 1000) {
        log.warn("Slow request: {} {} cost={}ms", request.getMethod(), request.getRequestURI(), cost);
    }
}

四、使用 Tomcat 线程堆栈定位“卡在哪里”

如果慢请求频繁,但日志看不出原因:

1. 抓取线程栈

jstack <tomcat_pid> > thread.log

2. 查找 HTTP 线程

grep -A 30 "http-nio" thread.log

常见现象:

  • WAITING on database connection
  • BLOCKED on synchronized
  • Socket read → 外部接口慢

五、使用 APM / 监控工具(生产最佳实践)

  • SkyWalking
  • Arthas
    trace com.xxx.controller.ApiController list
    
  • Prometheus + Grafana
  • Pinpoint / Zipkin

六、常见慢请求原因速查

现象 可能原因
偶发慢 GC、锁竞争
固定接口慢 SQL、外部调用
全部变慢 线程池满、CPU、DB
凌晨慢 备份、定时任务

七、总结建议

✅ 最小成本方案:

开启 %D 访问日志 + 阈值过滤

✅ 生产推荐:

应用层慢请求日志 + APM

如果你愿意,可以告诉我:

  • Tomcat 版本
  • 是否 Spring Boot
  • 慢请求是全部还是个别接口

我可以给你更精确的配置示例。

0 踩