千家信息网

微服务如何实现简单的分布式日志追踪

发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,这期内容当中小编将会给大家带来有关微服务如何实现简单的分布式日志追踪,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。最近想给项目添加一个简单的分布式请求跟踪功能,从前
千家信息网最后更新 2025年01月25日微服务如何实现简单的分布式日志追踪

这期内容当中小编将会给大家带来有关微服务如何实现简单的分布式日志追踪,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

最近想给项目添加一个简单的分布式请求跟踪功能,从前端发起请求到网关,再从网关调用 Spring Cloud 的微服务,这些过程中希望能从日志中看到一个分布式 ID 的链路,通过请求的 ID 可以追踪整一条链路,方便问题的排查。

现成的方案自然是使用 SkyWalking 、 Spring Cloud Sleuth 、Zipkin 之类的组件,但是想到主要的目的记录一个可以一直贯通各个服务的 ID,方便日志查询,也就不想引入太多复杂的组件,最终决定通过 MDC 在日志中输出追踪的 ID,然后在 Feign 和 RestTemplate 中将请求 ID 在微服务中传递。

主要包括几个步骤:

  • 从前端生成请求 ID 并加入请求头带入网关

  • 网关通过 WebFilter 拦截并加入 MDC 中,在 log 中输出

  • 在 Feign 和 RequestTemplate 中将请求 ID 在带到 HTTP 的 Header 中微服务传递

  • 各个微服务同样通过 WebFilter 实现拦截并加入 MDC,在 log 中输出

MDC

MDC(Mapped Diagnostic Context,映射调试上下文)是 Log4j 和 Logback 提供的一种方便在多线程条件下记录日志的功能。 MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。

MDC 的关键操作:

  • 向 MDC 中设置值:MDC.put(key, value);

  • 从 MDC 中取值:MDC.get(key);

  • 将 MDC 中内容打印到日志中:%X{key}

新增 TraceId 工具类

先新增一个 TraceIdUtils 工具类,用于定义 TRACE_ID 的常量值以及设置及生成 TRACE_ID 的方法,后续代码中都是通过这个估计类进行操作。

import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.MDC;  public class TraceIdUtils {     public static final String TRACE_ID = "traceId";     private static final int MAX_ID_LENGTH = 10;      /**      * 生成 traceId      */     private static String genTraceId() {         return RandomStringUtils.randomAlphanumeric(MAX_ID_LENGTH);     }      /**      * 设置 traceId      */     public static void setTraceId(String traceId) {         // 如果参数为空,则生成新 ID         traceId = StringUtils.isBlank(traceId) ? genTraceId() : traceId;         // 将 traceId 放到 MDC 中         MDC.put(TRACE_ID, StringUtils.substring(traceId, -MAX_ID_LENGTH));     }      /**      * 获取 traceId      */     public static String getTraceId() {         // 获取         String traceId = MDC.get(TRACE_ID);         // 如果 traceId 为空,则生成新 ID         return StringUtils.isBlank(traceId) ? genTraceId() : traceId;     } }

通过 WebFilter 添加 TraceId 过滤器

新增一个 GenericFilterBean ,从请求头中获取 TraceIdUtils.TRACE_ID 对应的值,该值在前端发起请求或者微服务之间传递都会带上,如果没有,则 TraceIdUtils.setTraceId 会生成一个。

import org.springframework.core.annotation.Order; import org.springframework.web.filter.GenericFilterBean;  @WebFilter(urlPatterns = "/*", filterName = "traceIdFilter") @Order(1) public class TraceIdFilter extends GenericFilterBean {     @Override     public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {         // traceId初始化         HttpServletRequest req = (HttpServletRequest) request;         String traceId = req.getHeader(TraceIdUtils.TRACE_ID);         TraceIdUtils.setTraceId(traceId);         // 执行后续过滤器         filterChain.doFilter(request, response);     } }

不要忘记在 SpringBoot 的启动类加上 @ServletComponentScan 注解,否则自定义的 Filter 无法生效。其中 "com.yourtion.trace.filter" 是 TraceIdFilter 所在的包名。

@ServletComponentScan(basePackages = "com.yourtion.trace.filter") @SpringBootApplication public class MyApplication {      public static void main(String[] args) {         SpringApplication.run(MyApplication.class, args);     } }

在 Feign 上添加 TraceId

因为 @FeignClient 的代理类在执行的时候,会去使用使用到 Spring 上下文的 RequestInterceptor,所以自定义自己的拦截器,然后注入到 Spring 上下文中,这样就可以在请求的上下文中添加自定义的请求头。

import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.stereotype.Service;  @Service public class FeignInterceptor implements RequestInterceptor {     @Override     public void apply(RequestTemplate template) {         template.header(TraceIdUtils.TRACE_ID, TraceIdUtils.getTraceId());     } }

在 RestTemplate 上添加 TraceId

还有一部分请求是通过 RestTemplate 发起的,之前我们是自己实现了 RestTemplateConfig 的配置类,这次在相关的配置上添加:

RestTemplate restTemplate = builder.additionalInterceptors((request, body, execution) -> {     request.getHeaders().add(TraceIdUtils.TRACE_ID, TraceIdUtils.getTraceId());     return execution.execute(request, body); }).build();

至此,链路上的 TraceId 添加已经完成,剩下的就是在日志中打印出来了。

修改 Log4j2 的 layout 格式

修改日志的layout格式,将MDC中的traceId打印出来:

    

上述就是小编为大家分享的微服务如何实现简单的分布式日志追踪了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

日志 服务 生成 分布式 上下 上下文 网关 内容 前端 链路 输出 中将 功能 就是 工具 格式 线程 组件 过滤器 分析 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全与计算机二级哪个难 做软件开发有多难 搜狗网络技术发展有限公司 杭州工行软件开发中心加班多吗 蒲城网络安全举报 国内互联网科技城市分布图 五华网络安全防线 数据库管理系统几个结构 pc端软件开发环境比较 实施网络安全审查办法 pycharm更新数据库 深圳众惠互联网科技有限公司 河北开源软件开发价格行情 麻省理工大学数据库 西藏算力服务器租赁收费标准 河南通讯软件开发设施有哪些 软件开发共享平台客户哪里找 电脑远程服务器返回错误403 土豆王国服务器要来到跳舞 DL380服务器系统下做阵列 国家网络安全宣传周主题餐厅 从事网络安全工作有风险吗 r语言访问plsql数据库 如何找到点赞过的服务器我的世界 网络安全隔离技术浅析 网络技术专科怎么毕业 高级网络安全系统测评师 山东网络安全周 网络安全与成长心得体会 软件开发公司长期目标
0