spring-cloud-sleuth3.x的版本传递traceId和⾃定义属性⽬录
为了简化后续做类似功能的童鞋操作,故整理⼀篇针对traceId和⾃定义属性全链路传递的处理操作,整体调试流程还是耽误了不少时间的。
要做的⽬标
实现全链路traceId传递,⾃定义全链路traceUrl标记(traceUrl的规则是⽐如:⽐如A-》B-》 C 这样得到的就是 traceUrl=/A/B/C)思路
1.依赖sleuth传递各种信息 ,使⽤⽅式遵循它的规则
2.feign调⽤处增加处理标记逻辑
3.web服务⼊⼝处增加拦截处理标记逻辑
4.异步线程池处理逻辑(sleuth⾃带功能)
实现
1.项⽬封装⼀个基础的jar包,⽐如trace-jar
A.依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
B.代码编写
/
/AOP处理feign逻辑前
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.util.StringUtils;springboot aop
@Aspect
public class FeignClientTraceAop {
@Around("@within(org.springframework.cloud.openfeign.FeignClient)")
Object around(final ProceedingJoinPoint pjp) throws Throwable {
String traceUrl = Baggage(TraceConstants.TRACE_KEY_TRACE_URL);
if (!StringUtils.hasText(traceUrl)) {
return pjp.proceed();
}
}
//常量类
import org.springframework.util.StringUtils;
public final class TraceConstants {
public static final String TRACE_KEY_TRACE_ID = "traceId";
public static final String TRACE_KEY_TRACE_URL = "traceUrl";
public static final String DELIMITER = "/";
public static final String APP_NAME_KEY = "appcode";
public static final String APP_NAME_DEFAULT = "MIS_APP_NAME";
private static String appName = null;
public static String getLocalAppName() {
if (appName != null) {
return appName;
}
appName = (APP_NAME_KEY);
if (StringUtils.hasText(appName)) {
return appName;
}
appName = APP_NAME_DEFAULT;
return appName;
}
//⼊⼝过滤器处理
import org.springframework.util.StringUtils;
import org.slf4j.MDC;
import javax.servlet.*;
import java.io.IOException;
public class TraceExtFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
///拦截⼀下把⾃⼰的 APPName处理掉
String traceUrl = Baggage(TraceConstants.TRACE_KEY_TRACE_URL);
String content;
if (!StringUtils.hasText(traceUrl)) {
content = TraceConstants.DELIMITER + LocalAppName();
} else {
content = traceUrl + TraceConstants.DELIMITER + LocalAppName();
}
MDC.put(TraceConstants.TRACE_KEY_TRACE_URL, content);
filterChain.doFilter(servletRequest, servletResponse);
}
/
/提供个Tracer静态接⼝,简化使⽤,容器不启动,不要直接使⽤否则逸出
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.cloud.sleuth.Span;
import t.ApplicationContext;
import t.ApplicationContextAware;
public class Tracer implements ApplicationContextAware {
private static final Logger logger = Logger(ace.Tracer.class);
private static org.springframework.cloud.sleuth.Tracer sleuthTracer;
public static String getTraceId() {
Span span = sleuthTracer.currentSpan();
t().traceId();
}
public static String getSpanId() {
return sleuthTracer.currentSpan().context().spanId();
}
public static void createBaggage(String key, String value) {
}
public static String getBaggage(String key) {
Baggage(key).get();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
try {
org.springframework.cloud.sleuth.Tracer bean = Bean(org.springframework.cloud.sleuth.Tracer.class); this.sleuthTracer = bean;
} catch (BeansException e) {
<("初始化trace功能异常,请检查org.springframework.cloud.sleuth.Tracer注⼊情况", e);
throw e;
}
}
//⾃动化注⼊类
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.sleuth.autoconfig.instrument.web.SleuthWebProperties;
import t.annotation.Bean;
import t.annotation.Configuration;
import Ordered;
@Configuration
public class TraceAutoConfiguration {
@Bean
Tracer delegateInnerTracer() {
return new Tracer();
}
@Bean
FeignClientTraceAop feignClientTraceAop() {
return new FeignClientTraceAop();
}
@Bean
public FilterRegistrationBean traceExtFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
TraceExtFilter filter = new TraceExtFilter();
registration.setFilter(filter);
registration.addUrlPatterns("/*");
registration.setName("trace-ext-filter");
registration.setOrder(SleuthWebProperties.TRACING_FILTER_ORDER + 1);
return registration;
}
}
//增加配置属性--这个点可以通过代码注⼊或者写到配置⽂件加载进去。具体实现可协商⾃⼰团队内部实现⽅式。// 注释:这两个配置属性就是⽤来传递和⼀以及可以写⼊到MDC 的
spring.lation-fields=traceUrl
spring.sleuth.baggage-keys=traceUrl
C:使⽤功能⽅增加依赖上上⼀步封装的jar包
//此步骤省略,看团队内部如何共享jar包,⽐如放到nexus(仓库)上公⽤,或者其他的使⽤⽅式。
理论上上边操作不需要使⽤⽅做任何操作,依赖上上边实现的对应功能即可。
模拟测试
假定⼀个server端提供接⼝,⼀个client端调⽤(feign),然后通过浏览器调⽤client。
形成链路:前端---》 client----> server
1.server端实现
提供⼀个简单接⼝(内部假定有线程池异步处理)
(注意点:线程池对象必须托管到spring容器内部才可传递)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论