}
MDC.clear();
}
编写Config类, 将拦截器TraceWebInterceptor添加到容器
@Configuration @ConditionalOnClass({HandlerInterceptorAdapter.class, MDC.class, HttpServletRequest.class}) public class TraceWebAutoConfiguration implements WebMvcConfigurer {
private static List<String> EXCLUDE_PATHS = new ArrayList<>();
@Value("${" + TraceConstants.CONFIG_TRACE_EXCLUDE_PATHS + ":}")
private String excludePaths;
@Bean
public TraceWebInterceptor traceWebInterceptor() {
return new TraceWebInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
EXCLUDE_PATHS.add("/error");
EXCLUDE_PATHS.add("/actuator/**");
if (StringUtils.isNotBlank(excludePaths)) {
if (excludePaths.contains(",")) {
String[] split = excludePaths.split(",");
EXCLUDE_PATHS.addAll(Arrays.asList(split));
} else {
EXCLUDE_PATHS.add(excludePaths);
}
}
//该方式不能过全部过滤掉
registry.addInterceptor(traceWebInterceptor()).order(-100).excludePathPatterns(EXCLUDE_PATHS);
}
}
工具类
public class IpUtil { private static final String UNKNOWN = "unknown";
public static String getIp(HttpServletRequest request) {
if (request == null) {
return UNKNOWN;
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
}
public class TraceConstants { public static final String LOG_TRACE_ORIGIN = "traceOrigin"; public static final String LOG_TRACE_CALLER = "traceCaller"; public static final String LOG_TRACE_IP = "traceIp"; public static final String LOG_TRACE_ID = "traceId";
public static final String CONFIG_TRACE_EXCLUDE_PATHS = "trace.exclude.paths";
public TraceConstants() {
}
}
import java.util.UUID; import org.apache.commons.lang3.StringUtils; import org.slf4j.MDC;
public class TraceUtil { private static boolean simbaHttpClientInterceptorFlag = true; private static boolean sdkInterceptorFlag = false; private static String applicationName;
public TraceUtil() {
}
public static void setApplicationName(String applicationName) {
TraceUtil.applicationName = applicationName;
}
public static String getApplicationName() {
return applicationName;
}
public static boolean getSimbaHttpClientInterceptorFlag() {
return simbaHttpClientInterceptorFlag;
}
public static void setSimbaHttpClientInterceptorFlag(boolean simbaHttpClientInterceptorFlag) {
TraceUtil.simbaHttpClientInterceptorFlag = simbaHttpClientInterceptorFlag;
}
public static boolean getSdkInterceptorFlag() {
return sdkInterceptorFlag;
}
public static void setSdkInterceptorFlag(boolean sdkInterceptorFlag) {
TraceUtil.sdkInterceptorFlag = sdkInterceptorFlag;
}
public static void setTraceCaller(String traceCaller) {
MDC.put("traceCaller", traceCaller);
}
public static String getTraceCaller() {
return MDC.get("traceCaller");
}
public static void setTraceOrigin(String traceOrigin) {
MDC.put("traceOrigin", traceOrigin);
}
public static String getTraceOrigin() {
return MDC.get("traceOrigin");
}
public static void setTraceId(String traceId) {
MDC.put("traceId", traceId);
}
public static void removeTraceId() {
MDC.remove("traceId");
}
public static void clearMdc() {
MDC.clear();
}
public static String getTraceId() {
return MDC.get("traceId");
}
public static String genTraceId() {
return UUID.randomUUID().toString().replace("-", "");
}
public static String getTraceIp() {
return MDC.get("traceIp");
}
public static void setTraceIp(String traceIp) {
MDC.put("traceIp", traceIp);
}
public static boolean loadTraceInfo() {
boolean generate = false;
String traceId = getTraceId();
if (StringUtils.isBlank(traceId)) {
traceId = genTraceId();
generate = true;
}
setTraceId(traceId);
return generate;
}
public static String getTraceInfoString() {
return "TraceId:" + getTraceId() + ". traceCaller:" + getTraceCaller() + ". traceOrigin:" + getTraceOrigin();
}
}
import org.slf4j.MDC;
import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit;
public class WrapUtil {
public static <T> Callable<T> wrap(final Callable<T> callable, final Map<String, String> context) {
return () -> {
if (context == null) {
MDC.clear();
} else {
MDC.setContextMap(context);
}
TraceUtil.loadTraceInfo();
try {
return callable.call();
} finally {
MDC.clear();
}
};
}
public static <T> Callable<T> wrap(final Callable<T> callable) {
return wrap(callable, MDC.getCopyOfContextMap());
}
public static Runnable wrap(final Runnable runnable, final Map<String, String> context) {
return () -> {
if (context == null) {
MDC.clear();
} else {
MDC.setContextMap(context);
}
TraceUtil.loadTraceInfo();
try {
runnable.run();
} finally {
MDC.clear();
}
};
}
public static Runnable wrap(final Runnable runnable) {
return wrap(runnable, MDC.getCopyOfContextMap());
}
public static ThreadPoolExecutor newThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
return new ThreadPoolExecutorMdcWrapper(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
public static ThreadPoolExecutor newThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
return new ThreadPoolExecutorMdcWrapper(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
}
public static ThreadPoolExecutor newThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
return new ThreadPoolExecutorMdcWrapper(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
public static ThreadPoolExecutor newThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
return new ThreadPoolExecutorMdcWrapper(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
}
public static ForkJoinPool newForkJoinPool() {
return new ForkJoinPoolMdcWrapper();
}
public static class ThreadPoolExecutorMdcWrapper extends ThreadPoolExecutor {
public ThreadPoolExecutorMdcWrapper(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
public ThreadPoolExecutorMdcWrapper(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
}
public ThreadPoolExecutorMdcWrapper(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
}
public ThreadPoolExecutorMdcWrapper(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
@Override
public void execute(Runnable task) {
super.execute(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public <T> Future<T> submit(Runnable task, T result) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), result);
}
@Override
public <T> Future<T> submit(Callable<T> task) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public Future<?> submit(Runnable task) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
}
public static class ForkJoinPoolMdcWrapper extends ForkJoinPool {
public ForkJoinPoolMdcWrapper() {
super();
}
public ForkJoinPoolMdcWrapper(int parallelism) {
super(parallelism);
}
public ForkJoinPoolMdcWrapper(int parallelism, ForkJoinWorkerThreadFactory factory,
Thread.UncaughtExceptionHandler handler, boolean asyncMode) {
super(parallelism, factory, handler, asyncMode);
}
@Override
public void execute(Runnable task) {
super.execute(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public <T> ForkJoinTask<T> submit(Runnable task, T result) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), result);
}
@Override
public <T> ForkJoinTask<T> submit(Callable<T> task) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
}
}
#### 2.2 Spring中的@Async注解中的线程池
@Configuration public class TaskExecutorConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = TraceSpringTraceWrapUtil.newThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
// 设置最大线程数
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10);
// 设置队列容量
executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(10);
// 设置默认线程名称
executor.setThreadNamePrefix("scheduled-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
}
相关工具类
import com.startdt.license.util.WrapUtil; import org.slf4j.MDC; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.util.concurrent.ListenableFuture;
import java.util.Date; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.RunnableScheduledFuture; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit;
public class TraceSpringTraceWrapUtil extends WrapUtil {
public static class ThreadPoolTaskExecutorMdcWrapper extends ThreadPoolTaskExecutor {
@Override
public void execute(Runnable task) {
super.execute(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public void execute(Runnable task, long startTimeout) {
super.execute(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), startTimeout);
}
@Override
public <T> Future<T> submit(Callable<T> task) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public Future<?> submit(Runnable task) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
return super.submitListenable(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
return super.submitListenable(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
}
public static class ScheduledThreadPoolTaskExecutorMdcWrapper extends ScheduledThreadPoolExecutor {
public ScheduledThreadPoolTaskExecutorMdcWrapper(int corePoolSize) {
super(corePoolSize);
}
public ScheduledThreadPoolTaskExecutorMdcWrapper(int corePoolSize, ThreadFactory threadFactory) {
super(corePoolSize, threadFactory);
}
@Override
protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> callable, RunnableScheduledFuture<V> task) {
return super.decorateTask(WrapUtil.wrap(callable, MDC.getCopyOfContextMap()), task);
}
@Override
protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task) {
return super.decorateTask(WrapUtil.wrap(runnable, MDC.getCopyOfContextMap()), task);
}
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
return super.schedule(WrapUtil.wrap(command, MDC.getCopyOfContextMap()), delay, unit);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return super.scheduleAtFixedRate(WrapUtil.wrap(command, MDC.getCopyOfContextMap()), initialDelay, period, unit);
}
}
public static class ThreadPoolTaskSchedulerWrapper extends ThreadPoolTaskScheduler {
@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
return super.schedule(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), startTime);
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
return super.schedule(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), trigger);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
return super.scheduleAtFixedRate(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), period);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
return super.scheduleAtFixedRate(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), startTime, period);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
return super.scheduleWithFixedDelay(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), delay);
}
}
public static ThreadPoolTaskExecutor newThreadPoolTaskExecutor() {
return new ThreadPoolTaskExecutorMdcWrapper();
}
public static ScheduledThreadPoolExecutor newScheduledThreadPoolExecutor(int corePoolSize) {
return new ScheduledThreadPoolTaskExecutorMdcWrapper(corePoolSize);
}
public static ScheduledThreadPoolExecutor newScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolTaskExecutorMdcWrapper(corePoolSize, threadFactory);
}
public static ThreadPoolTaskScheduler newThreadPoolTaskScheduler() {
return new ThreadPoolTaskSchedulerWrapper();
}
}
#### 2.3 spring线程池
import com.startdt.license.util.WrapUtil; import org.slf4j.MDC; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.util.concurrent.ListenableFuture;
import java.util.Date; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.RunnableScheduledFuture; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit;
public class TraceSpringTraceWrapUtil extends WrapUtil {
public static class ThreadPoolTaskExecutorMdcWrapper extends ThreadPoolTaskExecutor {
@Override
public void execute(Runnable task) {
super.execute(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public void execute(Runnable task, long startTimeout) {
super.execute(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), startTimeout);
}
@Override
public <T> Future<T> submit(Callable<T> task) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public Future<?> submit(Runnable task) {
return super.submit(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
return super.submitListenable(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
return super.submitListenable(WrapUtil.wrap(task, MDC.getCopyOfContextMap()));
}
}
public static class ScheduledThreadPoolTaskExecutorMdcWrapper extends ScheduledThreadPoolExecutor {
public ScheduledThreadPoolTaskExecutorMdcWrapper(int corePoolSize) {
super(corePoolSize);
}
public ScheduledThreadPoolTaskExecutorMdcWrapper(int corePoolSize, ThreadFactory threadFactory) {
super(corePoolSize, threadFactory);
}
@Override
protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> callable, RunnableScheduledFuture<V> task) {
return super.decorateTask(WrapUtil.wrap(callable, MDC.getCopyOfContextMap()), task);
}
@Override
protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task) {
return super.decorateTask(WrapUtil.wrap(runnable, MDC.getCopyOfContextMap()), task);
}
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
return super.schedule(WrapUtil.wrap(command, MDC.getCopyOfContextMap()), delay, unit);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return super.scheduleAtFixedRate(WrapUtil.wrap(command, MDC.getCopyOfContextMap()), initialDelay, period, unit);
}
}
public static class ThreadPoolTaskSchedulerWrapper extends ThreadPoolTaskScheduler {
@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
return super.schedule(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), startTime);
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
return super.schedule(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), trigger);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
return super.scheduleAtFixedRate(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), period);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
return super.scheduleAtFixedRate(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), startTime, period);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
return super.scheduleWithFixedDelay(WrapUtil.wrap(task, MDC.getCopyOfContextMap()), delay);
}
}
public static ThreadPoolTaskExecutor newThreadPoolTaskExecutor() {
return new ThreadPoolTaskExecutorMdcWrapper();
}
public static ScheduledThreadPoolExecutor newScheduledThreadPoolExecutor(int corePoolSize) {
return new ScheduledThreadPoolTaskExecutorMdcWrapper(corePoolSize);
}
public static ScheduledThreadPoolExecutor newScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolTaskExecutorMdcWrapper(corePoolSize, threadFactory);
}
public static ThreadPoolTaskScheduler newThreadPoolTaskScheduler() {
return new ThreadPoolTaskSchedulerWrapper();
}
}
#### 2.4 dubbo rpc
@Activate(group = {DubboConstants.CONSUMER} , order = -9999) public class TraceDubboConsumerFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(TraceDubboConsumerFilter.class);
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String traceId = TraceUtil.getTraceId();
String traceCaller = TraceUtil.getTraceCaller();
String traceOrigin = TraceUtil.getTraceOrigin();
if(StringUtils.isBlank(traceId)) {
traceId = TraceUtil.genTraceId();
traceCaller = TraceUtil.getApplicationName();
traceOrigin = TraceUtil.getApplicationName();
logger.debug("[仅生成追踪信息]traceId:{}. traceCaller:{}. traceOrigin:{}", traceId, traceCaller, traceOrigin);
}
RpcContext.getContext().setAttachment(TraceConstants.LOG_TRACE_ID, traceId);
RpcContext.getContext().setAttachment(TraceConstants.LOG_TRACE_CALLER, traceCaller);
RpcContext.getContext().setAttachment(TraceConstants.LOG_TRACE_ORIGIN, traceOrigin);
return invoker.invoke(invocation);
}
}
@Activate(group = {DubboConstants.PROVIDER}, order = -10000) public class TraceDubboProviderFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(TraceDubboConsumerFilter.class);
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//traceOrigin、traceCaller、traceId
String traceId = invocation.getAttachment(TraceConstants.LOG_TRACE_ID);
String traceCaller = invocation.getAttachment(TraceConstants.LOG_TRACE_CALLER);
String traceOrigin = invocation.getAttachment(TraceConstants.LOG_TRACE_ORIGIN);
//如果不存在traceId需要生成
if (StringUtils.isBlank(traceId)) {
boolean generate = TraceUtil.loadTraceInfo();
if(generate) {
logger.info("[生成追踪信息]" + TraceUtil.getTraceInfoString());
}
}else {
//设置MDC
MDC.put(TraceConstants.LOG_TRACE_ORIGIN, traceOrigin);
MDC.put(TraceConstants.LOG_TRACE_CALLER, traceCaller);
MDC.put(TraceConstants.LOG_TRACE_ID, traceId);
}
//IP
String clientIp = RpcContext.getContext().getRemoteHost();
MDC.put(TraceConstants.LOG_TRACE_IP, clientIp);
try {
return invoker.invoke(invocation);
} finally {
MDC.clear();
}
}
}
#### 2.5 kafka
生产者:
a:增加配置项:
spring: kafka: producer: properties: interceptor: classes: com.trace.kafka.TraceProducerInterceptor
b.kafkaTemplateAutoConfig代码中增加
if (StringUtils.isNotBlank(producerInterceptors)) { props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, producerInterceptors); }
消费者前增加代码:
TraceConsumerUtil.trace(consumerRecord);
消费者工具类
import com.startdt.simba.boot.common.constants.TraceConstants; import com.startdt.simba.boot.common.utils.TraceUtil; import org.apache.kafka.clients.consumer.ConsumerRecord;