目錄
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的功能只用到了鏈路的追蹤,項目依賴關系分析的部分沒有使用
