目录
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的功能只用到了链路的追踪,项目依赖关系分析的部分没有使用