分布式链路追踪核心概念
在微服务架构中,一个用户请求可能经过多个服务调用才能完成。当请求耗时增加或出现错误时,需要追踪请求在各个服务中的调用链路,定位瓶颈和故障节点。分布式链路追踪通过Trace(追踪)和Span(跨度)两个核心概念实现请求链路的可视化。
Trace代表一个完整的请求链路,由一个全局唯一的TraceId标识。Span代表链路中的一个操作单元,包含操作名称、开始时间、结束时间、标签和日志。Span之间通过父子关系构成调用树,每个Span携带ParentSpanId指向父Span,根Span的ParentSpanId为空。Trace Context(追踪上下文)通过HTTP Header在服务间传播,将TraceId和当前SpanId传递给下游服务,使下游服务生成的Span属于同一Trace。
Apache SkyWalking是开源的APM(应用性能监控)系统,支持链路追踪、指标采集和服务拓扑图可视化。SkyWalking通过Java Agent无侵入式采集链路数据,不需要修改应用代码。OpenTelemetry是CNCF维护的可观测性标准,定义了统一的Trace、Metric、Log数据模型和采集协议,SkyWalking从8.x版本开始支持OpenTelemetry协议(OTLP)格式的数据上报。
SkyWalking OAP Server集群部署
SkyWalking后端OAP(Observability Analysis Platform)Server负责接收、聚合和存储链路数据。生产环境使用集群部署保证高可用,存储使用Elasticsearch:
# docker-compose.yml - SkyWalking OAP集群
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms2g -Xmx2g"
volumes:
- es_data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
oap:
image: apache/skywalking-oap-server:9.7.0
environment:
- SW_STORAGE=elasticsearch
- SW_STORAGE_ES_CLUSTER_NODES=elasticsearch:9200
- SW_CLUSTER=standalone
- "JAVA_OPTS=-Xms1g -Xmx1g"
depends_on:
- elasticsearch
ports:
- "11800:11800" # gRPC端口,Agent数据上报
- "12800:12800" # HTTP端口,UI查询
ui:
image: apache/skywalking-ui:9.7.0
environment:
- SW_OAP_ADDRESS=http://oap:12800
depends_on:
- oap
ports:
- "8080:8080"
volumes:
es_data:
OAP Server的11800端口接收Agent通过gRPC上报的链路数据,12800端口提供HTTP查询API供UI访问。SW_STORAGE设置为elasticsearch指定存储后端,生产环境中Elasticsearch建议至少3节点集群。OAP Server支持水平扩展,多实例通过Zookeeper或Kubernetes进行集群协调,共享数据聚合任务。
Java Agent无侵入式接入配置
SkyWalking Java Agent通过字节码增强技术在类加载时注入追踪代码,无需修改应用源码。下载Agent包并配置启动参数:
# 下载并解压Agent
wget https://archive.apache.org/dist/skywalking/java-agent/9.2.0/apache-skywalking-java-agent-9.2.0.tgz
tar xzf apache-skywalking-java-agent-9.2.0.tgz
# 解压后目录结构: skywalking-agent/agent/skywalking-agent.jar
# 配置Agent (config/agent.config)
agent.service_name=order-service
collector.backend_service=oap.yunthe.com:11800
agent.span_limit=300
# 忽略指定路径的追踪
agent.ignore_path=/healthcheck,/actuator/**
# 采样率配置 (3.0格式)
agent.sample_n_per_3_secs=500
# JVM启动参数添加Agent
java -javaagent:/opt/skywalking-agent/agent/skywalking-agent.jar \
-jar order-service.jar
agent.service_name设置服务名称,在SkyWalking UI中作为拓扑图节点显示。collector.backend_service指定OAP Server的gRPC地址。agent.sample_n_per_3_secs设置采样率,每3秒采样500条链路,超过部分丢弃。生产环境高流量场景下采样率不宜设为全量(-1),避免OAP Server存储和聚合压力过大。
Spring Boot应用可在Dockerfile中集成Agent:
# Dockerfile
FROM eclipse-temurin:17-jre
# 安装SkyWalking Agent
COPY skywalking-agent /opt/skywalking-agent
# 应用配置
ENV JAVA_OPTS="-javaagent:/opt/skywalking-agent/agent/skywalking-agent.jar -Xms512m -Xmx512m"
ENV SW_AGENT_SERVICE_NAME=order-service
ENV SW_COLLECTOR_BACKEND_SERVICE=oap.yunthe.com:11800
COPY target/order-service.jar /app/order-service.jar
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/order-service.jar"]
Agent自动识别Spring MVC、Spring Cloud、OkHttp、MySQL Driver、Redis Client等常用框架的调用链路,在方法入口和出口自动创建Span,传播Trace Context。对于Agent未支持的框架,可通过@Trace注解或Toolkit API手动埋点:
// 手动埋点示例
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.apache.skywalking.apm.toolkit.trace.Tag;
public class OrderProcessor {
@Trace
@Tag(key = "orderId", value = "returned.orderId")
@Tag(key = "amount", value = "returned.amount")
public OrderResult processOrder(OrderRequest request) {
// 业务逻辑
return new OrderResult(request.getOrderId(), request.getAmount());
}
// 自定义Span和Tag
public void customSpan() {
TraceContext.putCorrelation("userId", "12345");
ActiveSpan.tag("custom.tag", "custom-value");
ActiveSpan.info("处理自定义业务逻辑");
// 业务逻辑
}
}
OpenTelemetry协议集成与跨语言追踪
OpenTelemetry定义了标准的Trace Context传播格式(W3C Trace Context),使用traceparent和tracestate两个HTTP Header传递追踪信息。SkyWalking 9.x原生支持OTLP协议,可通过OpenTelemetry SDK将链路数据上报到SkyWalking OAP Server。对于Java以外的语言(Go、Python、Node.js),使用OpenTelemetry SDK接入:
// Go服务使用OpenTelemetry SDK上报到SkyWalking
package main
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
)
func initTracer() func() {
ctx := context.Background()
// OTLP gRPC exporter,指向SkyWalking OAP
exporter, err := otlptracegrpc.New(ctx,
otlptracegrpc.WithEndpoint("oap.yunthe.com:11800"),
otlptracegrpc.WithInsecure(),
)
if err != nil {
panic(err)
}
// 配置资源信息
res, _ := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceName("payment-service"),
semconv.ServiceVersion("v1.2.0"),
),
)
// 创建TracerProvider
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(res),
sdktrace.WithSampler(sdktrace.TraceIDRatioBased(0.5)),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
return func() {
tp.Shutdown(ctx)
}
}
TraceIDRatioBased(0.5)设置50%采样率。propagation.TraceContext{}配置W3C Trace Context传播器,在HTTP/gRPC调用时自动注入和提取traceparent Header。当Java服务调用Go服务时,SkyWalking Java Agent注入的W3C Trace Context被OpenTelemetry Go SDK提取,两个Span被关联到同一Trace中,在UI中展示完整的跨语言调用链路。
在生产环境中,链路追踪数据的保留周期需要根据存储容量和排查需求平衡。SkyWalking支持按时间自动清理历史数据,通过core数据.minimum_day设置最小保留天数。对于关键链路数据,可导出到冷存储(如S3)长期保存。告警方面,SkyWalking提供Webhook告警机制,当响应时间P99超过阈值或错误率上升时触发告警通知。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/fen-bu-shi-lian-lu-zhui-zong-skywalkingjavaagent-jie-ru-yu/