Article

系统监控 SkyWalking

更新于:2026-07-14

第一章:SkyWalking 概述与核心概念

1.1 什么是 APM 与分布式追踪

概念名称说明注意事项
APM (Application Performance Management)应用性能管理,用于监控、分析和优化应用程序的性能和可用性。APM 不仅关注性能,也包含错误追踪、用户体验、业务指标等。
分布式追踪 (Distributed Tracing)在微服务或分布式系统中,追踪一个请求从入口到各服务的完整调用链路的技术。需要统一的追踪上下文传递机制(如 Trace Context)以保证跨服务链路的连续性。
调用链 (Trace)表示一个完整请求的执行路径,由多个 Span 组成。一个 Trace 通常对应一个用户请求或一个业务事务。
上下文传播 (Context Propagation)在服务调用间传递追踪信息(如 Trace ID、Span ID)的机制。常见传播格式:W3C Trace Context、B3 Headers。
性能瓶颈定位通过分析调用链的耗时分布,快速定位慢请求发生在哪个服务或方法。需结合日志、指标、追踪三位一体进行根因分析。

1.2 SkyWalking 架构概览(OAP Server, UI, Agent)

组件名称说明注意事项
Agent (探针)嵌入在应用中的 Java Agent,负责自动或手动收集追踪、指标等数据。零侵入或低侵入,通过字节码增强技术实现,对应用性能影响较小。
OAP Server (Observability Analysis Platform)接收 Agent 上报的数据,进行分析、聚合、存储,并提供查询接口。核心处理引擎,支持多种存储后端(如 Elasticsearch、MySQL、TiKV)。
UI (User Interface)提供可视化界面,用于查看拓扑图、调用链、性能指标、告警等信息。基于 Web 的前端,依赖 OAP Server 提供的 REST API 获取数据。
数据采集协议Agent 与 OAP Server 之间通过 gRPC 或 HTTP 协议传输数据。gRPC 性能更高,推荐生产环境使用;HTTP 便于调试。
插件机制Agent 支持多种中间件和框架的自动探针插件(如 Spring, Dubbo, MySQL)。插件可扩展,社区活跃,支持主流技术栈。

1.3 核心概念解析:Trace、Segment、Span、Service、Endpoint

概念名称说明注意事项
Trace一个完整请求的全局追踪标识,包含该请求在所有服务中的执行路径。所有相关 Span 共享同一个 Trace ID,用于跨服务关联。
Segment一个服务实例内,一次请求执行的代码段快照,由多个 Span 组成。Segment 是 SkyWalking 的数据上报单位,每个 Segment 包含一个或多个 Span。
Span表示一次操作的基本单元,如方法调用、数据库查询、HTTP 请求等。Span 有类型(Entry、Exit、Local),用于构建调用关系。
Service逻辑上的服务单元,通常对应一个微服务应用。多个实例(Instance)构成一个 Service。
Endpoint服务中的具体接口或方法,如 /user/getUserService.findById用于精细化监控接口级别的性能和错误率。
Trace ID全局唯一的字符串,标识一个完整的调用链。通常由第一个 Entry Span 生成,后续 Span 继承并传播。
Span ID在单个 Segment 内唯一,标识一个操作。与 Parent Span ID 构成树形结构。
Parent Span ID当前 Span 的父 Span 的 ID,用于构建调用层级。Root Span 的 Parent Span ID 为空。

第二章:环境搭建与快速入门

2.1 下载与安装 SkyWalking OAP Server

操作步骤说明注意事项
访问官方发布页前往 SkyWalking GitHub Releases 页面下载最新稳定版本。推荐使用最新稳定版(如 9.x),避免使用快照版本用于生产。
选择分发包下载 apache-skywalking-apm-x.x.x.tar.gz.zip 文件。包含 OAP Server 和 UI,无需单独下载。
解压安装包使用 tarunzip 解压到目标目录。确保路径无中文和空格,避免启动问题。
目录结构说明bin/:启动脚本;config/:配置文件;webapp/:UI 静态资源。config/application.yml 是 OAP Server 主配置文件。
存储后端配置默认使用 H2 内存数据库,生产环境需修改为 Elasticsearch 等持久化存储。需提前部署并配置好 Elasticsearch 集群。

2.2 启动 SkyWalking UI

操作步骤说明注意事项
配置 UI 端口修改 webapp/webapp.yml 中的 server.port(默认 8080)。若端口冲突,需修改为可用端口(如 8081)。
配置 OAP 地址确保 webapp/webapp.ymlcollector.ribbon.listOfServers 指向 OAP Server 地址。默认为 localhost:12800,若 OAP 部署在远程机器,需修改为对应 IP。
启动 OAP Server执行 bin/oapService.sh(Linux)或 bin/oapService.bat(Windows)。需先启动 OAP Server,再启动 UI。
启动 UI 服务执行 bin/webappService.shbin/webappService.batUI 启动较慢,等待日志出现 “Started Jetty in” 表示成功。
访问 UI 界面浏览器访问 http://<host>:<port>(如 http://localhost:8080)。首次访问可能无数据,需接入应用并产生请求。

2.3 使用 Java Agent 快速接入应用

操作步骤说明注意事项
找到 Agent 目录解压包中的 agent/ 目录包含探针文件。确保 Agent 目录路径无中文和空格。
启动参数配置在 Java 应用启动命令中添加 -javaagent:/path/to/skywalking-agent.jarAgent JAR 路径必须正确,建议使用绝对路径。
设置服务名添加 -Dskywalking.agent.service_name=my-service服务名应具有业务意义,避免重复。
设置 OAP 地址添加 -Dskywalking.collector.backend_service=localhost:11800端口 11800 是 gRPC 上报端口,确保 OAP Server 已监听。
完整启动命令示例java -javaagent:/opt/skywalking/agent/skywalking-agent.jar -Dskywalking.agent.service_name=demo-service -Dskywalking.collector.backend_service=192.168.1.100:11800 -jar myapp.jar可将参数写入脚本,便于管理。
容器化部署在 Dockerfile 或 Kubernetes 中挂载 Agent 目录并配置启动参数。注意容器内路径映射和权限问题。

2.4 验证数据上报与 UI 查看基础指标

操作步骤说明注意事项
触发应用请求调用已接入 Agent 的应用接口,产生业务流量。至少发起一次成功请求,确保数据生成。
查看服务拓扑图UI 首页”拓扑图”页面,查看服务间调用关系。新服务可能需要等待 1-2 分钟才会显示。
查看调用链 (Trace)进入”追踪”页面,筛选服务名,查看最近的 Trace 列表。点击 Trace 可查看详细 Span 信息和耗时。
查看 Metrics在”仪表板”中查看 QPS、响应时间、错误率等基础指标。指标为近实时,可能存在 10-30 秒延迟。
检查 Agent 日志查看应用日志或 agent/logs/skywalking-api.log 是否有错误。常见问题:网络不通、OAP 地址错误、端口未开放。
验证数据完整性确认 Trace 中包含预期的 Span(如 HTTP、DB 调用)。若缺少 Span,检查插件是否支持对应组件。

第三章:Java Agent 自动探针原理与配置

3.1 Java Agent 工作机制(Instrumentation)

概念名称说明注意事项
Java AgentJVM 提供的一种在类加载时动态修改字节码的机制,实现无侵入监控。需通过 -javaagent 参数启动,优先于应用代码加载。
Instrumentation APIJDK 提供的 java.lang.instrument 包,用于实现字节码增强。核心接口:Instrumentation,通过 premainagentmain 方法注入。
字节码增强 (Bytecode Enhancement)在类加载时修改其字节码,插入监控逻辑(如方法前后插入计时代码)。使用 ASM、Javassist 等库操作字节码,性能开销小。
ClassFileTransformerInstrumentation 接口注册的类文件转换器,对指定类进行字节码修改。可匹配类名、方法名、注解等条件进行精准增强。
Agent-ClassAgent 的入口类,包含 premain 方法,用于初始化探针逻辑。premain 方法在应用 main 方法前执行。
插件化架构SkyWalking Agent 使用插件机制,每个中间件(如 MySQL, Redis)有独立插件。插件定义匹配规则和增强逻辑,易于扩展和维护。
方法拦截 (Method Interceptor)在目标方法执行前后插入自定义逻辑(如记录开始/结束时间)。拦截器需处理异常,避免影响原方法执行。

3.2 Agent 核心配置文件详解(agent.config)

配置项名称说明注意事项
agent.service_name应用服务名称,显示在 UI 中。必须配置,建议使用小写字母和连字符,如 order-service
agent.sample_n_per_3_secs每 3 秒采样 Span 数量,默认 -1(全量)。生产环境建议设置合理采样率(如 10)以降低开销。
collector.backend_serviceOAP Server 的 gRPC 地址,格式为 <host>:<port>端口默认 11800,确保网络可达。
agent.namespace服务命名空间,用于多租户隔离。默认为空,按需配置。
agent.ignore_suffix配置忽略追踪的 URL 后缀,如 .css,.js,.png多个后缀用英文逗号分隔,减少静态资源干扰。
agent.cause_exception_depth记录异常堆栈的深度,默认 5。值越大记录越详细,但增加存储开销。
logging.levelAgent 自身日志级别,如 DEBUG, INFO, WARN, ERROR生产环境建议使用 INFOWARN
plugin.springmvc.use_short_urlSpring MVC 接口是否使用短 URL(去除路径参数)。设为 true 可聚合相同模式的接口(如 /user/1/user/{id})。
plugin.dubbo.collect_arguments是否收集 Dubbo 方法参数。参数可能包含敏感信息,按需开启。
profiling.active_controller_backends启用性能剖析功能的后端地址。高级功能,需配合 OAP 配置使用。

3.3 支持的中间件与框架自动探测

中间件/框架支持的功能注意事项
Spring MVC / WebFlux自动探测 HTTP 接口,生成 Entry Span。支持路径参数聚合,需配置 plugin.springmvc.use_short_url
Dubbo / gRPC接口级服务调用追踪,生成 Exit Span 和远程服务 Span。需确保服务提供方和消费方都接入 SkyWalking。
MySQL / PostgreSQLSQL 语句追踪,记录数据库操作、参数(可选)、执行时间。敏感参数可通过配置脱敏或关闭参数收集。
Redis (Jedis, Lettuce)Redis 命令追踪,如 GET, SET, HGET 等。不记录具体值,仅记录命令和 Key。
Kafka / RabbitMQ消息生产与消费链路追踪,支持上下文传播。消费者需正确配置,确保 Span 关联。
ElasticsearchREST/Transport Client 请求追踪。记录查询 DSL 片段(可配置),注意隐私。
OkHttp / HttpClientHTTP 客户端调用追踪,生成 Exit Span。支持异步调用链路传递。
ZooKeeperZK 客户端操作追踪,如 create, get用于分析服务发现性能。
ShardingSphere分库分表 SQL 与执行计划追踪。需使用 SkyWalking 支持的版本。
Log4j2 / Logback通过 MDC 自动注入 Trace ID,实现日志与追踪关联。需启用日志插件并配置 MDC 输出 %X{trace_id}

3.4 排除特定类或方法的追踪

配置方式说明注意事项
agent.ignore_suffixagent.config 中配置 URL 后缀,忽略静态资源或健康检查接口。适用于 Web 接口,如 /health,/info,.css
trace.ignore.path通过 JVM 参数设置忽略的 HTTP 路径,多个路径用英文逗号分隔。优先级高于 agent.ignore_suffix,如 -Dtrace.ignore.path=/health,/metrics
插件排除规则在插件配置中禁用特定中间件的探测(如不监控 Redis)。修改 agent/config/ 下对应插件的启用开关。
自定义 Ignore 字段在代码中通过设置 Span Tag 忽略上报(需结合手动埋点)。非标准做法,不推荐。
字节码匹配排除通过修改插件源码或扩展插件,添加类/方法匹配排除规则。高级用法,需重新打包 Agent。
环境变量配置使用环境变量覆盖 agent.config 配置,便于容器化部署。SW_AGENT_IGNORE_SUFFIX=.js,.css

第四章:手动埋点与 OpenTracing API

4.1 OpenTracing 核心接口概述(Tracer, Span, Scope)

接口名称说明注意事项
Tracer用于创建 Span 和管理追踪上下文的核心工厂接口。SkyWalking 通过 GlobalTracer.get() 获取实例。
Span表示一个操作的基本单元,包含操作名、开始时间、标签、日志等信息。必须显式结束(span.finish())以正确上报。
SpanContextSpan 的上下文信息,包含 Trace ID、Span ID、Baggage 等。用于跨服务传递追踪信息。
Scope表示当前线程的活动 Span,通过 ScopeManager 管理。使用 try-with-resources 确保自动关闭。
ScopeManager管理线程本地的当前 Span(active span),处理跨线程传递。SkyWalking 使用 ThreadLocal 存储当前 Span。
Baggage在 SpanContext 中传递的键值对数据,随整个 Trace 传播。不用于监控,仅用于业务数据传递,避免滥用。
Reference定义 Span 间的引用关系,如 CHILD_OFFOLLOWS_FROMSkyWalking 主要使用 CHILD_OF 构建树形调用链。

4.2 创建和结束 Span

方法名称 / 操作语法用途代码示例注意事项
Tracer.buildSpantracer.buildSpan("operationName")创建 Span 构建器,指定操作名称。Tracer tracer = GlobalTracer.get();
Span span = tracer.buildSpan("userService.findById").start();
操作名应具有业务语义,便于在 UI 中识别。
AbstractSpan.setOperationNamespan.setOperationName("newName")动态修改 Span 的操作名称。span.setOperationName("user-query");通常在创建时指定,运行时修改较少。
Span.startspan.start()显式启动 Span,记录开始时间。span.start();buildSpan 后需调用 start() 才真正开始计时。
Span.finishspan.finish()结束 Span,记录结束时间并准备上报。span.finish();必须调用,否则 Span 不会上报且可能内存泄漏。
try-with-resources + Scopetry (Scope scope = tracer.buildSpan(...).startActive(true)) { ... }自动管理 Scope 生命周期,确保 Span 正确结束。try (Scope scope = tracer.buildSpan("businessLogic").startActive(true)) {
// 业务代码
}
推荐方式,避免忘记 finish
Span.log(Throwable)span.log(event)记录异常事件到 Span 日志中。span.log(new RuntimeException("DB timeout"));可结合 Tag "error" = true 标记错误 Span。

4.3 添加 Span 标签(Tags)与日志(Logs)

方法名称 / 操作语法用途代码示例注意事项
Span.setTag(String key, String value)span.setTag("key", "value")为 Span 添加字符串类型的标签。span.setTag("user.id", "12345");
span.setTag("error", "true");
常用标签:error, db.type, http.method
Span.setTag(String key, boolean value)span.setTag("error", true)添加布尔类型标签,常用于标记错误。span.setTag("error", exception != null);SkyWalking UI 会根据 error=true 高亮显示错误 Span。
Span.setTag(String key, Number value)span.setTag("http.status_code", 200)添加数字类型标签,如状态码、数量。span.setTag("http.status_code", response.getStatus());便于后续聚合分析。
Span.log(long timestamp, Map<String,?> fields)如右在指定时间点记录结构化日志事件。Map<String, Object> log = new HashMap<>();
log.put("event", "cache.miss");
log.put("key", "user:1");
span.log(System.currentTimeMillis(), log);
可记录缓存命中、重试次数等事件。
Span.log(String event)span.log("cache.hit");记录简单的事件名称。span.log("db.query.start");
span.log("db.query.end");
事件名应具有可读性。
内置标准标签常量Tags.HTTP_METHOD, Tags.HTTP_STATUS, Tags.DB_TYPE, Tags.ERROR使用 OpenTracing 规范的预定义标签,提高兼容性。span.setTag(Tags.HTTP_METHOD, "GET");
span.setTag(Tags.ERROR, true);
推荐使用标准标签,便于工具解析。

4.4 跨线程传递上下文(Scope Manager)

方法名称 / 操作语法用途代码示例注意事项
tracer.scopeManager().active()Scope activeScope = tracer.scopeManager().active();获取当前线程的活动 Scope。Scope parentScope = tracer.scopeManager().active();若无活动 Span,返回 null
Scope.span()Span activeSpan = activeScope.span();从 Scope 中获取当前活动 Span。Span parentSpan = parentScope.span();用于跨线程传递 SpanContext。
SpanContext.injectcarrier.inject(activeSpan.context(), Format.Builtin.HTTP_HEADERS, httpHeaders);将 SpanContext 注入到载体(如 HTTP Headers)中。TextMapInjectAdapter carrier = new TextMapInjectAdapter(headers);
activeSpan.context().inject(Format.Builtin.HTTP_HEADERS, carrier);
使用 W3C 或 B3 格式进行跨服务传播。
SpanContext.extractSpanContext extractedContext = tracer.extract(Format.Builtin.HTTP_HEADERS, carrier);从载体(如 HTTP Headers)中提取 SpanContext。TextMapExtractAdapter carrier = new TextMapExtractAdapter(headers);
SpanContext ctx = tracer.extract(Format.Builtin.HTTP_HEADERS, carrier);
消费方用于恢复调用链上下文。
try (Scope ignored = tracer.activateSpan(extractedContext)) { ... }在新线程中激活提取的 SpanContext,创建新的本地 Span。try (Scope scope = tracer.activateSpan(remoteContext)) {
// 新线程中的代码
}
确保跨线程调用链连续。
异步任务包装使用 CompletableFuture 时手动传递上下文。保持异步调用链路完整。如左SkyWalking 自动探针支持部分异步框架,手动埋点需特别注意。

4.5 设置 Span 层级关系(Parent-Child)

方法名称 / 操作语法用途代码示例注意事项
tracer.buildSpan(operationName).start()默认使用当前线程的活动 Span 作为父 Span。创建子 Span,自动关联父 Span。try (Scope parent = tracer.buildSpan("parent").startActive(true)) {
Span child = tracer.buildSpan("child").start();
child.finish();
}
最常用方式,依赖 ScopeManager。
tracer.buildSpan(operationName).asChildOf(Parent)tracer.buildSpan("child").asChildOf(parentSpan).start()显式指定父 Span,构建父子关系。Span child = tracer.buildSpan("db.query").asChildOf(serviceSpan).start();当无法使用 Scope 时使用。
tracer.buildSpan(operationName).withActiveSpan()tracer.buildSpan("child").withActiveSpan().start()显式使用当前活动 Span 作为父 Span(与默认行为一致)。Span child = tracer.buildSpan("local.task").withActiveSpan().start();代码更明确,可读性好。
tracer.buildSpan(operationName).ignoreActiveSpan()tracer.buildSpan("independent").ignoreActiveSpan().start()忽略当前活动 Span,创建独立的 Span(无父 Span)。Span independent = tracer.buildSpan("background.job").ignoreActiveSpan().start();用于完全独立的任务,不希望影响主调用链。
Reference.CHILD_OFtracer.buildSpan("child").addReference(References.CHILD_OF, parentContext).start()使用 OpenTracing 标准引用方式建立父子关系。如左标准做法,但 asChildOf 更简洁。
Root Span在无活动 Span 时创建的第一个 Span 成为 Root Span。构成 Trace 的起点。Entry Span(如 HTTP 请求)通常是 Root Span。一个 Trace 有且仅有一个 Root Span。

第五章:OpenTelemetry 与 SkyWalking 集成

5.1 OpenTelemetry SDK 基本使用

方法名称 / 操作语法用途代码示例注意事项
OpenTelemetry.getGlobalTracerProvider()Tracer tracer = OpenTelemetry.getGlobalTracerProvider().get("my-library");获取全局 Tracer 实例。Tracer tracer = OpenTelemetry.getGlobalTracerProvider().get("demo-app");需先配置并设置全局 SDK,否则返回默认无操作实现。
Tracer.spanBuilderSpan span = tracer.spanBuilder("operation").startSpan();创建 Span 构建器并启动 Span。Span span = tracer.spanBuilder("getData").startSpan();必须调用 startSpan() 才真正创建 Span。
Span.setAttributespan.setAttribute("key", "value")为 Span 添加属性(等同于 Tag)。span.setAttribute("user.id", "1001");支持 String、long、double、boolean 及其数组类型。
Span.addEventspan.addEvent("eventName")在 Span 中记录一个事件(等同于 Log)。span.addEvent("cache.miss");可带属性:span.addEvent("retry", Attributes.of("count", 2));
Span.recordExceptionspan.recordException(exception)记录异常信息,自动设置 error=true 属性。try { ... } catch (Exception e) { span.recordException(e); }推荐方式标记错误,自动填充异常消息和堆栈。
span.end()span.end()结束 Span,释放资源并准备上报。span.end();必须调用,否则造成内存泄漏。
try (Scope scope = span.makeCurrent())try (Scope scope = span.makeCurrent()) { ... }将 Span 设置为当前线程的活动 Span。try (Scope scope = span.makeCurrent()) {
// 此范围内当前 Span 为 span
}
推荐使用 try-with-resources 确保自动清理。
SdkTracerProvider.builder()SdkTracerProvider.builder().addSpanProcessor(...).build()构建自定义 Tracer Provider,用于配置处理器。如 5.2 节示例通常在应用初始化时配置一次。

5.2 使用 OTLP 上报数据到 SkyWalking

方法名称 / 操作语法用途代码示例注意事项
OtlpGrpcSpanExporter.builder()OtlpGrpcSpanExporter.builder().setEndpoint("http://oap:11800").build()创建 OTLP gRPC Span 上报器,指向 SkyWalking OAP。OtlpGrpcSpanExporter exporter = OtlpGrpcSpanExporter.builder()
.setEndpoint("http://localhost:11800")
.build();
端口 11800 是 SkyWalking OAP 的 OTLP gRPC 接收端口。
BatchSpanProcessor.builder()BatchSpanProcessor.builder(exporter).build()创建批处理处理器,缓冲 Span 并批量上报。BatchSpanProcessor processor = BatchSpanProcessor.builder(exporter).build();比 SimpleSpanProcessor 性能更好,减少网络开销。
SdkTracerProvider.builder()SdkTracerProvider.builder().addSpanProcessor(processor).build()将处理器注册到 Tracer Provider。SdkTracerProvider provider = SdkTracerProvider.builder()
.addSpanProcessor(processor)
.build();
一个 Provider 可添加多个处理器。
OpenTelemetrySdk.builder()OpenTelemetrySdk.builder().setTracerProvider(provider).build()构建完整的 OpenTelemetry SDK 实例。OpenTelemetrySdk sdk = OpenTelemetrySdk.builder()
.setTracerProvider(provider)
.build();
需设置为全局实例:OpenTelemetry.setGlobalTelemetry(sdk);
Resource.create()Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "my-service"))创建资源对象,设置服务名等全局属性。Resource resource = Resource.create(Attributes.of(
ResourceAttributes.SERVICE_NAME,
"order-service"
));
必须设置 service.name,否则 SkyWalking 无法识别服务。
设置环境变量export OTEL_EXPORTER_OTLP_ENDPOINT=http://oap:11800通过环境变量配置 OTLP 端点,无需代码配置。export OTEL_EXPORTER_OTLP_ENDPOINT=http://192.168.1.10:11800适用于容器化部署,优先级低于代码配置。

5.3 映射 OpenTelemetry 数据到 SkyWalking 模型

OpenTelemetry 概念SkyWalking 映射目标说明注意事项
Trace IDTrace ID全局唯一标识,直接透传。格式兼容,无需转换。
Span IDSpan ID操作唯一标识,直接透传。SkyWalking 使用相同 ID 空间。
Parent Span IDParent Span ID构建调用树的父子关系。OTel 的 Parent ID 对应 SkyWalking 的 Parent Span ID。
Span Kind (CLIENT, SERVER, INTERNAL, PRODUCER, CONSUMER)Span Type (Exit, Entry, Local)CLIENT/PRODUCER → Exit; SERVER/CONSUMER → Entry; INTERNAL → Local。SkyWalking 通过此映射构建拓扑图和服务依赖。
Service Name (Resource)Service Name逻辑服务名称,来自 Resource 属性。必须设置 service.name 属性。
Operation NameEndpoint Name / Span Operation接口或操作名称,如 HTTP 路径、方法名。SkyWalking UI 按此名称聚合。
Attributes (key-value)Tags透传为 Span 的标签。标准属性(如 http.method, db.statement)被 SkyWalking 语义化解析。
EventsLogsOTel 事件映射为 SkyWalking Span 日志。包含时间戳和结构化字段。
Status (OK, ERROR)Error TagStatus=ERROR 时设置 error=true 标签。SkyWalking 根据此标记错误请求。
Instrumentation Library无直接对应记录埋点库信息,SkyWalking 用作元数据。不影响核心模型,用于调试和溯源。

第六章:高级特性与自定义监控

6.1 自定义指标(Metrics)上报

方法名称 / 操作语法用途代码示例注意事项
MeterProvider.get("name")Meter meter = OpenTelemetry.getMeter("my-meter");获取 Meter 实例,用于创建指标。Meter meter = OpenTelemetry.getMeter("jvm-monitor");类似 Tracer,通过名称获取。
Meter.counterBuilderCounter counter = meter.counterBuilder("requests.count").build();创建计数器,单调递增。Counter reqCounter = meter.counterBuilder("http.requests").build();适用于请求数、错误数等。
Counter.addcounter.add(1, "key", "value")增加计数器值,并可添加标签。reqCounter.add(1, "method", "GET", "path", "/api/user");原子操作,线程安全。
Meter.upDownCounterBuilderUpDownCounter upDownCounter = meter.upDownCounterBuilder("queue.size").build();创建可增可减的计数器。如左适用于队列大小、连接数等。
UpDownCounter.addupDownCounter.add(1);
upDownCounter.add(-1);
增加或减少计数器值。activeConnections.add(1);
activeConnections.add(-1);
值可为负。
Meter.histogramBuilderHistogram histogram = meter.histogramBuilder("response.time").build();创建直方图,用于统计分布(如响应时间)。Histogram respHist = meter.histogramBuilder("http.resp.time").build();SkyWalking 可计算 P90、P99 等。
Histogram.recordhistogram.record(100.5, "path", "/api/user");记录一个测量值。respHist.record(responseTime, "method", request.getMethod());值通常为正数。
LongSumObserver / DoubleSumObserver通过 Callback 注册异步指标采集。采集不频繁变化的指标,如 JVM 内存。meter.sumObserverBuilder("jvm.memory.used")
.setDescription("Used memory")
.setUnit("bytes")
.buildWithCallback(observer -> {
observer.observe(getMemoryUsed(), "area", "heap");
});
异步上报,避免频繁调用。

6.2 添加全局标签(Global Tags)

配置方式说明注意事项
agent.config 配置agent.config 中设置 agent.global_tags = tag1=value1,tag2=value2所有自动和手动创建的 Span 都会携带这些标签。
JVM 系统属性启动时添加 -Dskywalking.agent.global_tags=env=prod,region=us-east优先级高于配置文件,便于不同环境动态设置。
OpenTelemetry Resource在 OTel 中通过 Resource 设置全局属性。Resource resource = Resource.create(Attributes.of("env", "prod", "version", "1.0"));
Agent 插件扩展通过自定义插件在运行时动态添加标签(如从 MDC 读取)。高级用法,需开发插件。
环境变量设置 SW_AGENT_GLOBAL_TAGS=service.version=1.2.0与 JVM 参数效果相同,适用于容器环境。
注意事项全局标签会增加每个 Span 的大小,避免设置过多或过大的值。建议仅设置关键维度,如 envversionregion

6.3 使用插件扩展探针能力

操作步骤说明注意事项
创建插件模块新建 Maven 模块,依赖 skywalking-java-agent-plugin-define遵循 SkyWalking 插件命名规范。
定义 Instrumentation继承 ClassInstanceMethodsEnhancePluginDefine,指定目标类和方法。可使用字节码匹配表达式(如 *Controller)精准定位。
实现 StaticMethodsAroundInterceptor编写拦截器,在方法前后插入逻辑。onMethodEnter() 中创建 Span,onMethodExit() 中结束 Span。
配置 plugin.def 文件resources/META-INF/services/ 下创建文件,注册插件。格式:插件类全名=增强类全名。
打包插件 JAR将插件 JAR 放入 agent/plugins/ 目录。Agent 启动时自动加载。
调试插件启用 agent 日志 DEBUG 级别,观察插件加载和拦截日志。使用 SkyWalking 提供的调试工具。
版本兼容性插件需与 Agent 版本兼容,关注 API 变更。建议使用稳定版本的 API。

6.4 日志与追踪上下文关联(Logging MDC)

配置方式说明注意事项
启用日志插件SkyWalking Agent 自带 log4j2/logback 插件,自动注入 MDC。确保 agent.config 中插件已启用(默认开启)。
MDC 键名trace_id, trace_id_readable, span_id, parent_span_id, service_name, endpoint_name在日志格式中使用这些键名输出上下文。
日志框架配置logback.xmllog4j2.xml 中配置 PatternLayout 包含 MDC 字段。例如:%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %X{trace_id} %msg%n
手动设置 MDC(备用)在代码中使用 MDC.put("trace_id", span.getSpanContext().getTraceId());仅在 Agent 未生效时使用,避免重复设置。
日志收集系统将包含 Trace ID 的日志发送到 ELK 或其他日志系统。在 Kibana 等工具中可通过 Trace ID 关联查看日志和调用链。
跨线程传递MDC 通常不跨线程,需使用特殊处理(如 TtlMDC)或依赖 Agent 自动处理。SkyWalking 插件会尽量保证异步场景下的上下文传递。
性能影响MDC 操作有轻微开销,但通常可忽略。避免在高频日志中频繁操作 MDC。

第七章:性能分析与告警

7.1 查看调用链(Trace)与拓扑图

功能区域操作说明注意事项
服务拓扑图 (Topology)在 SkyWalking UI 首页查看全局服务依赖关系图,节点为服务,连线为调用关系。颜色深浅表示调用量或延迟,红色表示高错误率。
服务列表 (Service List)查看所有已注册服务,可按名称、类型、SLA、响应时间等排序和筛选。点击服务进入详情页,查看其调用链、指标等。
调用链查询 (Trace)在”Trace”页面,通过服务名、端点、时间范围、Trace ID 等条件查询调用链。支持高级搜索,如 status:error 查看所有错误调用。
调用链详情点击单条 Trace 查看完整的 Span 层级结构,展示调用顺序、耗时、标签和事件。可展开每个 Span 查看详细属性,定位耗时瓶颈。
关联日志在 Span 详情中查看注入的 Trace ID 和 Span ID,用于在日志系统中关联查询。需确保日志框架已正确配置 MDC。
端点 (Endpoint)查看服务内具体接口(如 /api/user/{id})的性能指标和调用链。可分析特定接口的 P99、QPS、错误率。
服务实例 (Instance)查看服务每个实例的健康状况和资源消耗(需开启 JVM 插件)。用于排查单个实例异常。
浏览器端监控 (Browser)查看前端页面的性能数据(加载时间、AJAX 调用),与后端调用链关联。需在前端页面引入 SkyWalking 的 JS Agent。

7.2 分析慢调用与错误率

分析方法操作步骤工具/功能
慢调用分析1. 在 Trace 页面按响应时间排序。
2. 选择高延迟的 Trace。
3. 查看 Span 耗时分布,定位慢操作(如 DB、RPC)。
调用链详情图、Span 耗时柱状图。
错误率分析1. 在服务或端点详情页查看 Error Rate 指标。
2. 在 Trace 搜索中使用 status:error
3. 分析错误 Span 的异常日志和堆栈。
错误率曲线图、错误调用链列表、异常堆栈信息。
指标对比对比不同时间段、不同服务实例的响应时间、QPS、错误率,识别异常波动。SkyWalking UI 的指标对比功能(时间范围选择器)。
数据库慢查询查看 DB 类型的 Exit Span,分析 SQL 语句和执行时间。需确保 DB 插件已启用并能捕获 SQL。
缓存效率分析 Redis/Memcached 调用的耗时和频率,判断缓存命中率。通过 Exit Span 的操作类型(GET/SET)和耗时判断。
外部服务依赖检查调用第三方 API 的 Exit Span,确认是否为瓶颈或错误源。关注 HTTP 状态码、响应时间。
JVM 性能查看服务实例的 CPU、内存、GC 情况,判断是否资源不足导致性能下降。需开启 JVM 插件,查看实例监控指标。
自定义指标分析结合自定义 Metrics(如队列长度、锁等待时间)进行综合分析。在 Metrics 页面查询自定义指标。

7.3 设置告警规则(Alarm Rules)

规则类型配置示例说明
服务级别规则service_resp_time_rule: endpointName IN (GET /api/user) AND resp_time > 1000当特定端点响应时间超过 1000ms 触发告警。
服务实例规则instance_jvm_memory_rule: serviceName = "order-service" AND instance_jvm_memory > 80当服务实例 JVM 内存使用率超过 80% 触发告警。
端点规则endpoint_error_rate_rule: endpointName = "/api/pay" AND error_rate > 5当支付接口错误率超过 5% 触发告警。
服务关系规则service_relation_resp_time_rule: destServiceName = "user-service" AND resp_time > 2000当调用用户服务的响应时间超过 2000ms 触发告警。
指标阈值支持 resp_time, error_rate, p99, p95, qps, heap_memory, cpu 等。可组合多个条件(AND/OR)。
告警周期period: 5(评估周期为 5 分钟)在每个周期内指标持续满足条件才触发。
持续时间count: 3(连续 3 个周期满足条件)避免瞬时抖动导致误报。
忽略时间silence_period: 3(告警后 3 个周期内不再重复触发)防止告警风暴。
配置文件位置config/alarm-settings.yml修改后 OAP Server 需要重启或热加载(取决于版本)。

7.4 告警通知渠道配置(Webhook, 邮件等)

通知渠道配置方法注意事项
Webhookalarm-settings.yml 中配置 Webhook URL 和消息模板。可集成企业微信、钉钉、飞书、Slack 等。
邮件 (Email)配置 SMTP 服务器、发件人、收件人列表。需提供 SMTP 地址、端口、用户名、密码。
gRPC配置 gRPC 服务端地址,SkyWalking 通过 gRPC 发送告警数据。适用于自定义告警处理服务。
Slack提供 Slack Webhook URL 或使用 Bot 集成。需在 Slack 中创建 Incoming Webhook。
钉钉 (DingTalk)使用自定义机器人 Webhook,支持加签。Webhook URL 需包含 access_token,可设置安全加签。
企业微信 (WeCom)使用群机器人 Webhook。支持文本、Markdown 消息格式。
飞书 (Lark)使用自定义机器人 Webhook。类似钉钉,支持富文本消息。
消息模板可自定义告警消息内容,包含服务名、实例、指标、阈值、时间等变量。确保信息清晰,便于快速响应。
多渠道通知可同时配置多个渠道,确保告警不遗漏。例如:邮件 + 钉钉。
安全性避免在配置中硬编码敏感信息(如密码),使用环境变量或密钥管理服务。部分版本支持从环境变量读取配置。

第八章:生产环境最佳实践

8.1 Agent 性能开销评估与调优

优化项配置建议效果
采样率 (Sampling)设置 agent.sample_n_per_3_secs=1 或使用百分比采样。降低数据量,减少网络和存储开销。
批处理大小调整 collector.backend_service 的批量发送大小和间隔。平衡延迟与吞吐量。
日志级别生产环境使用 INFO 或 WARN,避免 DEBUG。减少 Agent 自身日志开销。
禁用不必要的插件agent.config 中将 plugin.xxx.enable=false如禁用未使用的 DB、MQ 插件,减少字节码增强开销。
内存限制为 Agent 分配合理内存,避免频繁 GC。通常默认配置已足够,高负载服务可适当增加。
异步上报确保使用 BatchSpanProcessor 而非 SimpleSpanProcessor。减少对应用线程的阻塞。
监控 Agent 开销使用 JVM 监控工具(如 JConsole)观察 Agent 对 CPU 和内存的影响。评估性能影响,确保 < 5%。
升级到最新版本新版本通常包含性能优化和 Bug 修复。定期评估升级。
避免高频日志埋点不在循环或高频调用中创建 Span 或记录事件。防止产生海量 Span 导致 OAP 压力过大。

8.2 安全配置(认证、加密)

安全措施配置方法说明
OAP 通信加密启用 TLS/SSL,配置 collector.grpc.ssl.*collector.rest.ssl.*保护 Agent 与 OAP 之间的数据传输。
认证 (Authentication)在 OAP 端启用 JWT 或 Basic Auth,Agent 配置相应 token 或凭证。防止未授权 Agent 上报数据。
Agent 配置加密敏感配置(如数据库密码)使用加密,Agent 启动时解密。SkyWalking 本身不直接支持,需结合外部方案。
网络隔离将 OAP Server 部署在内网,通过防火墙限制访问。仅允许 Agent 所在服务器访问 OAP 的 11800/12800 端口。
RBAC (基于角色的访问控制)在 UI 层(如通过 Nginx 或前端网关)实现用户权限管理。控制不同用户对监控数据的查看和操作权限。
数据脱敏在插件中对敏感信息(如用户 ID、手机号)进行脱敏处理后再上报。避免隐私数据泄露。
定期审计审查 Agent 配置、OAP 日志和访问记录。及时发现安全风险。
更新依赖库及时更新 Agent 和 OAP 的第三方库,修复已知漏洞。使用 dependency-check 等工具扫描。

8.3 多环境(Dev/Test/Prod)配置管理

环境Agent 配置建议OAP 配置建议数据存储建议
开发 (Dev)- 高采样率或全量采集
- 启用所有插件
- 日志级别 DEBUG
- 上报到独立 OAP
- 使用轻量级存储(如 H2)
- 开启调试日志
- 允许更多探针连接
本地或开发环境专用存储,数据可定期清理
测试 (Test)- 中等采样率
- 启用核心插件
- 日志级别 INFO
- 上报到测试 OAP
- 使用独立集群
- 存储保留周期较短
- 配置基本告警
测试专用 ES/MySQL 实例,与生产隔离
生产 (Prod)- 低采样率
- 仅启用必要插件
- 日志级别 WARN
- 启用 TLS 加密和认证
- 高可用集群
- 大容量存储
- 严格的安全策略
- 配置关键业务告警
独立、高性能、高可用的存储(如 ES 集群)
通用策略- 使用 -Dskywalking.agent.service_name=service-name-env 区分环境
- 通过环境变量或配置中心管理配置
- 使用 Ansible/Puppet 统一部署
- 通过 namespace 或 service_name 前缀区分环境数据
- 使用不同的索引/数据库
严格隔离,禁止跨环境访问

8.4 高可用部署 OAP Server

部署组件高可用方案说明
OAP Server 集群部署多个 OAP 实例,通过负载均衡(如 Nginx、HAProxy)对外提供服务。Agent 上报数据可被任意实例接收,后端存储需共享。
后端存储- Elasticsearch: 部署 ES 集群(多节点、多副本)
- MySQL: 主从复制或使用云数据库高可用版
存储是 OAP 的核心依赖,必须高可用。
ZooKeeper / Consul用于 OAP 集群的协调和服务发现(部分部署模式需要)。如使用 gRPC 接收器时,Agent 可通过服务发现找到 OAP 实例。
数据一致性OAP 无状态,所有实例连接同一后端存储,数据一致性由存储层保证。确保存储的写入性能和可靠性。
负载均衡在 OAP 前部署 LB,Agent 配置 LB 地址作为上报端点。支持 gRPC 和 HTTP 流量。
健康检查配置 LB 的健康检查路径(如 /v3/health)。及时剔除故障节点。
自动伸缩根据 CPU、内存或消息队列积压情况,对 OAP 实例进行水平扩展。适用于流量波动大的场景。
容灾备份定期备份 ES/MySQL 数据,制定灾难恢复计划。确保监控数据不丢失。
监控 OAP 自身使用外部监控系统(如 Prometheus + Grafana)监控 OAP 的 JVM、GC、队列等指标。及时发现 OAP 性能瓶颈或故障。