java - 如何跟踪普通 Spring 微服务应用程序(非 Spring boot)中的请求?

标签 java spring http spring-mvc optimization

如何在普通 Spring 微服务应用(非 Spring boot)中跟踪请求? 我知道 Spring boot 提供了 Sleuth,但我想对非 Spring boot 应用程序执行类似的操作,它是一个普通的 Spring 应用程序。当请求通过不同的微服务时,我们想要跟踪它们。

最佳答案

  1. 您需要配置 Spring 应用程序以使用 logback.xml 文件进行日志记录。
  2. 创建一个拦截器,像 Sleuth 一样设置额外的 MDC 上下文
  3. 您需要将相同的附加 MDC 上下文传递给 HTTP header 中的其他服务。

登录配置

<configuration>
      <appender class="ch.qos.logback.core.ConsoleAppender" name="STDOUT">
        <encoder>
          <pattern>[%date{dd-MM-yyyy HH:mm:ss.SSS}]  [%thread] %-5level %X{traceId:-} %X{spanId:-} ${PID:-} %logger{36} - %msg%n</pattern>
        </encoder>
      </appender>
      <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILE">
        <encoder>
          <pattern>[%date{dd-MM-yyyy HH:mm:ss.SSS}]  [%thread] %-5level %X{traceId:-} %X{spanId:-} ${PID:-} %logger{36} - %msg%n</pattern>
        </encoder>
        <file>log/app.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
          <fileNamePattern>log/app.%d{yyyy-MM-dd-HH}.log</fileNamePattern>
          <maxHistory>30</maxHistory>
          <totalSizeCap>200MB</totalSizeCap>
        </rollingPolicy>
      </appender>

      <logger level="INFO" name="root">
        <appender-ref ref="STDOUT"/>
      </logger>
    </configuration>

设置 MDC 上下文以进行跟踪的拦截器。

@Slf4j
public class LoggerInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    String traceId = request.getHeader("TRACE_ID");
    String spanId = request.getHeader("SPAN_ID");
    if (traceId == null) {
      traceId = UUID.randomUUID().toString();
    }
    // You can generate new spanId or use the same one
    if (spanId == null) {
      spanId = UUID.randomUUID().toString();
    }
    MDC.put("TRACE_ID", traceId);
    MDC.put("traceId", traceId);
    MDC.put("SPAN_ID", spanId);
    MDC.put("spanId", spanId);
    log.info("[preHandle] HTTP: {}, URL: {} ", request.getMethod(), request.getRequestURI());
    return true;
  }

  @Override
  public void postHandle(
      HttpServletRequest request,
      HttpServletResponse response,
      Object handler,
      ModelAndView modelAndView)
      throws Exception {
    log.info("[postHandle] HTTP: {}, URL: {} ", request.getMethod(), request.getRequestURI());
    MDC.clear();
  }
}

如果您想测量执行时间,请为其添加分析器。在 Profiling Spring Boot 的示例中了解更多相关信息,它具体说明了 Spring boot,但您也可以在 Spring 应用程序中使用相同的方法。

如果您使用 RestTemplate,则可以设置这些 header 。

  HttpHeaders headers = new HttpHeaders();
  headers.set("TRACE_ID", MDC.get("TRACE_ID"));
  headers.set("SPAN_ID", MDC.get("SPAN_ID"));

  HttpEntity entity = new HttpEntity(headers);
  RestTemplate restTemplate = new RestTemplate();
  SimpleClientHttpRequestFactory rf =
      (SimpleClientHttpRequestFactory) restTemplate.getRequestFactory();
  rf.setReadTimeout(2 * Constants.ONE_MILLI_INT);
  rf.setConnectTimeout(2 * Constants.ONE_MILLI_INT);
  ResponseEntity<String> response =
      restTemplate.exchange(url, HttpMethod.GET, entity, String.class);

在这个简单的示例中,已设置 TRACE_IDSPAN_ID header 。

关于java - 如何跟踪普通 Spring 微服务应用程序(非 Spring boot)中的请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62083662/

相关文章:

java - 使用 JPA 事务处理 Spring 批处理错误

asp.net - 处理原始 HTTP 请求内容

java - 如何解决松散耦合/依赖性注入(inject)与富域模型之间的冲突?

java - 为什么我在 Log4J 中得到 double like 输出?

java - TreeMap - 为什么即使在其中添加超过 2 个元素后它也只返回 1 的大小?

database - 手动为 hibernate UUID 赋值

ios - AFHTTPClient 将授权 header 字段设置为 "Token token='\75845hjhrtje84539574 8' "但我只想成为里面的 token

c# - Internet Explorer 在保存/打开文件时显示乱码?

java - 从 gradle osgi 插件切换到 org.dm.bundle 插件时出错

java - 哪些技术适合人类工作流程系统?