国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - 編程技術 - 微服務實現簡單的分布式日志追蹤

微服務實現簡單的分布式日志追蹤

2021-01-25 23:20Yourtion的博客Yourtion 編程技術

最近想給項目添加一個簡單的分布式請求跟蹤功能,從前端發起請求到網關,再從網關調用 Spring Cloud 的微服務,這些過程中希望能從日志中看到一個分布式 ID 的鏈路,通過請求的 ID 可以追蹤整一條鏈路,方便問題的排查。

最近想給項目添加一個簡單的分布式請求跟蹤功能,從前端發起請求到網關,再從網關調用 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打印出來:

<!-- 原始格式 --> 

<PatternLayout pattern="%5p %c:%L - %m %throwable{separator( --> )}%n"/> 

 

<!-- 增加traceId的格式 --> 

<PatternLayout pattern="%5p traceId:%X{traceId} %c:%L - %m %throwable{separator( --> )}%n"/> 

至此,修改就大功告成了。

原文地址:https://blog.yourtion.com/microservice-simple-distributed-log-tracing.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久久综合网 | 成人精品一区二区 | 日韩精品一区二区三区四区 | 美日韩一区二区 | 久久久99精品免费观看 | 亚洲欧美自拍视频 | 五月天婷婷国产精品 | 婷婷精品 | 一区二区三区精品视频免费看 | 精品国偷自产在线 | 高清在线一区二区 | 国产精品a久久 | 亚洲www视频| 国产精品极品美女在线观看免费 | 中文字幕在线综合 | 午夜精品一区二区三区在线播放 | 国产精品免费看片 | 精品欧美 | 亚洲欧美日韩国产综合 | 成人高清在线 | 久久久国产精品视频 | 欧美在线网站 | 精品国产一区二区三区久久久 | 女人夜夜春高潮爽av片 | 久久久久国产精品免费 | 久久久精品网 | 狠狠操影院 | 高清一区二区三区 | 色综合88 | 欧美日韩一区二区三区不卡视频 | 国产欧美在线 | 999这里只有是极品 最新中文字幕在线 | 精品成人一区二区三区 | 欧美日韩第一页 | 超碰免费观看 | 欧美精品日韩精品 | 亚洲国产精品一区二区久久 | 久久久久久久久综合 | 亚洲一区 中文字幕 | 欧美二区三区 | 日本高清视频在线播放 |