什么是全链路日志监控
微服务全链路日志监控是指在分布式微服务架构中,对多个微服务应用之间的调用关系进行监控的一种方法。这种监控可以理解为对代码的调用进行监控,其目的是在出现问题时,能够通过可视化界面快速定位和解决问题。
在微服务架构中,系统为了接收并处理一个前端用户请求,需要多个微服务应用协同工作。这些微服务应用可能使用不同的编程语言构建,由不同的团队开发,并分布在多台服务器上。单个用户请求会经过多个微服务,相互之间形成复杂的调用关系。因此,传统的监控手段已经不能实现如此复杂的链路之间的监控,需要一些可以帮助理解系统行为、用于分析性能问题的工具。
全链路监控就是其中的一种方法,它对微服务之间的调用关系进行监控,了解每个应用如何调用。这样可以实现对整个微服务链路的监控,从用户请求到各个微服务的调用过程都可以被监控到。
什么是traceId
全链路日志的traceId是一种分布式全局唯一id标识,由系统第一个被调起的模块生成,并在各个span间传递。通过spanId和traceId可以定位到具体的模块的一次请求。
在微服务架构中,由于系统调用链路长且复杂,使用traceId可以帮助快速定位问题。当出现问题时,通过查看日志中traceId的调用链路,可以迅速找到问题所在,提高排错效率。
单应用日志链路监控
单应用的日志链路监控实现比较简单,本文就不做赘述了。可自行百度 “ Spring Boot+MDC 实现全链路调用日志跟踪” 。本文主要解决如下两个问题
- 异步线程,如何保障 tradeId 的传递
- 跨微服务,如何保障 tradeId 的传递
异步线程,如何保障 tradeId 的传递
当我们在应用中使用线程池时,会发现tradeId未按照预期进行传递。当主线程第一次设置traceId后,线程池线程再次被复用时,仍是首次设置的traceId。
使用 TestThreadPoolExecutor 解决这个问题,代码如下。可以发现,每次循环请求,线程池线程被复用时,都可以获取到主线程设置的 traceId
import com.alibaba.ttl.threadpool.TtlExecutors;
public class TestThreadPoolExecutor {
ExecutorService executorService;
public TestThreadPoolExecutor(int i, int i1, long l, TimeUnit timeUnit, BlockingQueue<Runnable> blockingQueue) {
executorService = TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor(i, i1, l, timeUnit, blockingQueue));
}
public TestThreadPoolExecutor(int i, int i1, long l, TimeUnit timeUnit, BlockingQueue<Runnable> blockingQueue, ThreadFactory threadFactory) {
executorService = TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor(i, i1, l, timeUnit, blockingQueue, threadFactory));
}
public TestThreadPoolExecutor(int i, int i1, long l, TimeUnit timeUnit, BlockingQueue<Runnable> blockingQueue, RejectedExecutionHandler rejectedExecutionHandler) {
executorService = TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor(i, i1, l, timeUnit, blockingQueue, rejectedExecutionHandler));
}
public TestThreadPoolExecutor(int i, int i1, long l, TimeUnit timeUnit, BlockingQueue<Runnable> blockingQueue, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
executorService = TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor(i, i1, l, timeUnit, blockingQueue, threadFactory, rejectedExecutionHandler));
}
public ExecutorService getExecutorService() {
return executorService;
}
public void setExecutorService(ExecutorService executorService) {
this.executorService = executorService;
}
}