1. 简介

在微服务或 Web 服务开发中,了解用户如何与我们的服务交互是非常有价值的。一种常见的做法是追踪所有进入服务的 HTTP 请求,并将这些数据收集起来用于后续分析。

虽然市面上有 Zipkin 等专门的分布式追踪系统可以集成(比如通过 Sleuth + Zipkin),但其实 Spring Boot Actuator 自带了轻量级的请求追踪能力,通过其内置的 httptrace 接口即可实现。本文将介绍如何启用和定制这一功能,让它更贴合实际需求。

✅ 适用场景:调试、审计、性能初步分析
❌ 不适合替代完整的 APM(如 SkyWalking、Pinpoint)


2. 启用 httptrace 接口

我们以一个标准的 Maven 构建的 Spring Boot 项目为例。

首先,引入 spring-boot-starter-actuator 依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

接着,在 application.properties 中暴露 httptrace 接口:

management.endpoints.web.exposure.include=httptrace

⚠️ 生产环境请注意安全!建议配合 management.endpoints.web.exposure.exclude=* 再选择性暴露,或通过安全配置限制访问 IP/权限。

启动应用后,访问 /actuator 可看到当前启用的接口列表:

{
  "_links": {
    "self": {
      "href": "http://localhost:8080/actuator",
      "templated": false
    },
    "httptrace": {
      "href": "http://localhost:8080/actuator/httptrace",
      "templated": false
    }
  }
}

此时访问 http://localhost:8080/actuator/httptrace 即可获取最近的请求记录。


3. 分析追踪数据结构

调用几次服务接口后再请求 httptrace,返回示例如下:

{
  "traces": [
    {
      "timestamp": "2019-08-05T19:28:36.353Z",
      "principal": null,
      "session": null,
      "request": {
        "method": "GET",
        "uri": "http://localhost:8080/echo?msg=test",
        "headers": {
          "accept-language": [ "en-GB,en-US;q=0.9,en;q=0.8" ],
          "upgrade-insecure-requests": [ "1" ],
          "host": [ "localhost:8080" ],
          "connection": [ "keep-alive" ],
          "accept-encoding": [ "gzip, deflate, br" ],
          "accept": [ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" ],
          "user-agent": [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 ..." ]
        },
        "remoteAddress": null
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Length": [ "12" ],
          "Date": [ "Mon, 05 Aug 2019 19:28:36 GMT" ],
          "Content-Type": [ "text/html;charset=UTF-8" ]
        }
      },
      "timeTaken": 82
    }
  ]
}

关键字段说明:

  • timestamp:请求到达时间(ISO 8601 格式)
  • principal:认证用户信息(如使用 Spring Security)
  • session:会话 ID(如有)
  • request:包含方法、URI、请求头、远端地址
  • response:响应状态码与响应头
  • timeTaken:处理耗时(毫秒)

自定义返回字段

默认返回信息较全,可能包含敏感头或冗余数据。可通过配置精简输出:

management.trace.http.include=RESPONSE_HEADERS

可选值(枚举 Include)包括:

  • URL
  • QUERY_PARAMETERS
  • REQUEST_HEADERS
  • RESPONSE_HEADERS
  • COOKIES
  • TIME_TAKEN
  • PRINCIPAL
  • SESSION_ID
  • REMOTE_ADDRESS

✅ 常见组合示例:

# 只关心路径、耗时和状态
management.trace.http.include=URL,TIME_TAKEN,RESPONSE_HEADERS

修改后,响应中未包含的字段将被剔除或设为 null,减少网络传输开销。


4. 自定义 HttpTraceRepository

⚠️ 默认实现 InMemoryHttpTraceRepository 有两个限制:

  • 最多保存最近 100 条 请求
  • 数据存在内存中,重启即丢失

若想持久化存储或调整容量,需自定义 HttpTraceRepository 实现。

下面是一个简单示例:仅保留最近一次 GET 请求 的追踪记录。

@Repository
public class CustomTraceRepository implements HttpTraceRepository {

    private final AtomicReference<HttpTrace> lastTrace = new AtomicReference<>();

    @Override
    public List<HttpTrace> findAll() {
        HttpTrace trace = lastTrace.get();
        return trace != null ? Collections.singletonList(trace) : Collections.emptyList();
    }

    @Override
    public void add(HttpTrace trace) {
        if ("GET".equals(trace.getRequest().getMethod())) {
            lastTrace.set(trace);
        }
    }
}

✅ 进阶思路:

  • 存入 Redis / MongoDB,支持跨实例共享
  • 结合 Kafka 异步写入日志系统
  • 按时间窗口滚动清理(如保留最近 1 小时)

只要实现 HttpTraceRepository 接口,Spring Boot Actuator 会自动使用你的 bean 替代默认实现。


5. 过滤不需要追踪的路径

默认情况下,所有请求都会被记录 —— 包括对 /actuator/** 本身的访问,这往往会造成干扰。

例如你可能会看到类似这样的 trace:

{
  "request": {
    "method": "GET",
    "uri": "http://localhost:8080/actuator/httptrace"
  }
}

要排除特定路径,只需注册一个自定义 HttpExchangeFilter(注意类名已更新,旧文中的 HttpTraceFilter 已废弃):

@Component
public class TraceRequestFilter extends HttpExchangesFilter {

    public TraceRequestFilter(HttpTraceRepository repository) {
        super(repository, Include.defaultIncludes());
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String path = request.getServletPath();
        return path.contains("/actuator") || path.equals("/health");
    }
}

📌 踩坑提示:

  • 必须继承 HttpExchangesFilter 并传入 repositoryincludes
  • shouldNotFilter 返回 true 表示 跳过追踪
  • 推荐排除 /actuator, /swagger-ui, /health 等管理或静态资源路径

6. 总结

Spring Boot Actuator 提供的 httptrace 接口是一个轻量、开箱即用的 HTTP 请求追踪方案,适合用于:

  • 快速排查问题
  • 审计关键接口调用
  • 简单性能观测(timeTaken

核心能力总结:

功能 配置方式
启用接口 management.endpoints.web.exposure.include=httptrace
控制输出字段 management.trace.http.include=...
自定义存储 实现 HttpTraceRepository
路径过滤 继承 HttpExchangesFilter,重写 shouldNotFilter

💡 小建议:生产环境慎用,避免影响性能或泄露敏感信息。如需完整链路追踪,建议升级到 Sleuth + Zipkin 或 SkyWalking。

完整示例代码已托管至 GitHub:https://github.com/example/spring-boot-httptrace-demo


原始标题:Logging HTTP Requests with Spring Boot Actuator HTTP Tracing

« 上一篇: Eclipse 调试指南