springboot+dubbo整合sleuth+zipkin實現鏈路追蹤


目錄

  1.項目背景

  2.整體架構圖

  3.鏈路效果

    1.返回數據

    2.zipkin效果

  4.技術實現

    1.pom依賴

    2.在springweb項目中添加 traceId

    3.在logback中添加 traceId

    4.zipkin搭建

項目背景

  在搭建新的springcloud + dubbo 項目框架的時候,負責實現全局鏈路追蹤,從請求通過網關到最后通過網關返回數據有一個全局的 TraceId 可以追蹤

  1.前端可看到 TraceId 

  2.業務日志能看到 TraceId 

  3.在zipkin中能檢索到 TraceId 走過的鏈路信息

  4.能夠做到全程不需要人工編碼參與

整體項目架構

 

實現原理:在各個服務的入口處添加過濾器,http請求和dubbo都一樣,設置TraceId,通過上下文在當前項目中傳遞

3.鏈路效果

  1.返回數據

{
    "code": "00000",
    "data": {
        "looked": 0
    },
    "message": "SUCCESS",
    "page": null,
    "traceId": "588f31cbe8319733"
}

  2.zipkin效果

 

 

 

 

4.技術實現

1.pom依賴

<!--zipkin依賴中包含了sleuth依賴-->
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> <version>2.2.5.RELEASE</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-instrumentation-dubbo</artifactId> <version>5.12.6</version> </dependency>

2.在springweb項目中添加 traceId

  在統一的返回實體中給 traceId字段賦值

//統一返回實體
public
class Result<T> implements Serializable { private static final long serialVersionUID = -8373949364192372417L; private String code; private String message; private T data; private Page page; private String traceId; }
import brave.Tracer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 初始化 {@linkplain HandlerMethodReturnValueHandlerProxy} 注入參數 Tracer並代理 {@linkplain HandlerMethodReturnValueHandler}
 * 添加到 handlerAdapter.getReturnValueHandlers()中
 */
@Configuration
public class RestReturnValueHandlerConfig implements InitializingBean {
    @Resource
    private RequestMappingHandlerAdapter handlerAdapter;
    @Resource
    private Tracer trace;

    @Override
    public void afterPropertiesSet() {List<HandlerMethodReturnValueHandler> list = handlerAdapter.getReturnValueHandlers();
        List<HandlerMethodReturnValueHandler> newList = new ArrayList<>();
        if (list != null) {
            for (HandlerMethodReturnValueHandler valueHandler : list) {
                if (valueHandler instanceof RequestResponseBodyMethodProcessor) {
                    HandlerMethodReturnValueHandlerProxy proxy = new HandlerMethodReturnValueHandlerProxy(valueHandler, trace);
                    newList.add(proxy);
                } else {
                    newList.add(valueHandler);
                }
            }
        }

        handlerAdapter.setReturnValueHandlers(newList);
    }
}

 

import brave.Tracer;
import com.aicloud.common.core.entity.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

/** * 自定義rest統一結果返回值處理器 */ public class HandlerMethodReturnValueHandlerProxy implements HandlerMethodReturnValueHandler { private HandlerMethodReturnValueHandler proxyObject; private Tracer trace; public HandlerMethodReturnValueHandlerProxy(HandlerMethodReturnValueHandler proxyObject, Tracer trace) { this.proxyObject = proxyObject; this.trace = trace; } /** * 不修改原始的支持類型 */ @Override public boolean supportsReturnType(MethodParameter returnType) { return proxyObject.supportsReturnType(returnType); } /** * 添加 traceId * * @param returnValue 返回值如果為{@linkplain Result}添加 */ @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { if (returnValue instanceof Result) { String traceIdString = trace.currentSpan().context().traceIdString(); if (StringUtils.isNotEmpty(traceIdString)) { ((Result) returnValue).setTraceId(traceIdString); } } proxyObject.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } }
#配置文件
spring: zipkin: base
-url: http://localhost:9411/ sender: type: web discoveryClientEnabled: false sleuth: sampler: probability: 1.0

 

3.在logback中添加 traceId信息

 

<!-- [%X{X-B3-TraceId:-},%X{X-B3-SpanId:-} 是traceId配置-->
<property name="encoder_pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}[%thread] %-5level [%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}] %logger{50} - %msg%n"/>

 

4.zipkin搭建

  參照zipkin 官方地址: https://zipkin.io/pages/quickstart.html

   注:本項目中zipkin的功能只用到了鏈路的追蹤,項目依賴關系分析的部分沒有使用

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM