SkyWalking 线程池异步任务链路追踪
SkyWalking 线程池异步任务链路追踪
环境说明
- JDK 版本:1.8
- SkyWalking Agent 版本:8.14.0
- Spring Boot 版本:2.7.11
- 依赖库:
<dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm-toolkit-trace</artifactId> <version>8.10.0</version> </dependency>
异步跟踪支持
Apache SkyWalking 提供了一套包装类来支持编程方式下的异步跟踪。这些包装类可以确保在使用线程池或并行流时,跟踪上下文(如 Trace ID)能够正确地在异步任务之间传播。
| 包装类名称 | 包装的原始接口 | 应用场景 |
|---|---|---|
RunnableWrapper | Runnable | 当您需要将 Runnable 任务提交给执行器时使用。 |
SupplierWrapper | Supplier | 在创建一个异步供给型任务时使用,例如 CompletableFuture.supplyAsync。 |
FunctionWrapper | Function | 当您需要对流中的元素进行转换操作时使用,适用于并行流。 |
CallableWrapper | Callable | 当您需要从异步任务中返回结果时使用。 |
ConsumerWrapper | Consumer | 对流中的每个元素执行操作时使用,适用于并行流。 |
示例代码
线程池中传递 Trace ID
对于线程池,您可以使用 RunnableWrapper 和 CallableWrapper 来包装您的任务,以确保跟踪上下文的正确传播。
import org.apache.skywalking.apm.toolkit.trace.RunnableWrapper;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RunnableWrapperExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
// 使用 RunnableWrapper 包装任务
executor.submit(RunnableWrapper.of(() -> {
System.out.println("异步任务执行中...");
}));
executor.shutdown();
}
}
CompletableFuture 中传递 Trace ID
对于 CompletableFuture,您可以使用 SupplierWrapper 来包装供给型异步任务。
import org.apache.skywalking.apm.toolkit.trace.SupplierWrapper;
import java.util.concurrent.CompletableFuture;
public class SupplierWrapperExample {
public static void main(String[] args) {
// 使用 SupplierWrapper 包装任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(
SupplierWrapper.of(() -> "异步任务结果")
);
future.thenAccept(System.out::println).join();
}
}
ParallelStream 并行流中传递 Trace ID
当处理并行流时,可以分别使用 FunctionWrapper 和 ConsumerWrapper 来包装流中的转换和消费操作。
import org.apache.skywalking.apm.toolkit.trace.FunctionWrapper;
import org.apache.skywalking.apm.toolkit.trace.ConsumerWrapper;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamWrapperExamples {
private static void functionWrapperExample() {
List<String> list = Arrays.asList("A", "B", "C", "D");
List<String> result = list.parallelStream()
.map(FunctionWrapper.of(item -> item + " processed"))
.collect(Collectors.toList());
result.forEach(System.out::println);
}
private static void consumerWrapperExample() {
List<String> list = Arrays.asList("A", "B", "C", "D");
list.parallelStream()
.forEach(ConsumerWrapper.of(item -> System.out.println(item + " processed")));
}
public static void main(String[] args) {
functionWrapperExample();
consumerWrapperExample();
}
}
最佳实践
- 一致性:始终使用相同的包装类来包裹同类型的任务,以保持项目的一致性和可维护性。
- 错误处理:为异步任务实现适当的错误处理机制,确保即使发生异常,跟踪信息也不会丢失。
- 性能考量:注意过度包装可能会引入额外的开销,在性能敏感的应用中应权衡利弊。
- 文档化:记录下为何以及如何在特定情况下使用这些包装类,有助于团队成员理解代码意图。
通过遵循上述指导原则,您可以在应用程序中有效地实施异步任务的链路追踪,从而简化调试和性能分析过程。
参考文档
官方文档:Trace Cross Thread
SkyWalking线程池异步任务链路追踪
359

被折叠的 条评论
为什么被折叠?



