SkyWalking
1. 分布式追踪与核心概念
SkyWalking 用于分析分布式应用的调用关系、延迟、错误和资源使用情况。以“网关 → 订单服务 → 库存服务 → 数据库”为例,可以从一个慢请求定位到具体的下游调用、数据库访问或应用代码。
| 概念 | 含义 | 使用要点 |
|---|---|---|
| Service | 一个逻辑应用,如 prod::orders-api | 同一应用的多个副本使用同一服务名 |
| Service Instance | 服务的运行实例,如一个 Pod 或进程 | 实例名需要区分副本,不能全部写成同一个固定值 |
| Endpoint | 服务处理的操作,如 GET:/orders/{id} | 使用路由模板,避免订单号等动态值造成高基数 |
| Trace | 一次分布式请求的追踪上下文 | 多个进程通过上下文传播关联到同一个 Trace |
| Segment | 一个线程或执行上下文中的一组 Span | 跨进程、跨线程通过引用关联,不等于完整 Trace |
| Span | 一次操作的开始、结束、状态及标签 | 常见类型为 Entry、Exit、Local |
Trace ID 关联整条请求;Span ID 在所属 Segment 内使用,不能只拿 Span ID 在不同进程间关联。同步调用、线程池、异步任务和消息消费都有各自的传播机制,只有插件支持或正确使用 Toolkit,才能把上下游关联起来。
追踪系统适合回答“慢在哪一跳”“错误发生在哪个服务”“哪个依赖影响了入口”。服务指标用于观察趋势,Trace 用于分析具体请求,日志用于补充业务上下文,Profiling 用于进一步定位热点代码。平均响应时间不能代替 P95/P99,也不能把成功率指标直接当成经过业务定义的 SLO。
2. 架构、端口与版本
业务请求:客户端 → 网关 → 应用服务 → 数据库 / 缓存 / MQ
│ Agent 采集与上报
▼
OAP Server
│ ▲
写入/查询 │ 查询 API
▼ │
存储 ← OAP ← UI ← 浏览器
- Agent:为受支持的框架自动埋点,传递追踪上下文,采集应用指标和 Trace。
- OAP:接收数据、聚合指标、分析拓扑、执行告警并读写存储。
- 存储:保存 Trace、指标、日志、告警及管理数据。OAP 10.4 可使用 Elasticsearch、OpenSearch、BanyanDB 等后端。
- UI:通过 OAP 的查询接口展示数据,不直接连接 Elasticsearch。
| 端口 | 用途 | 访问范围 |
|---|---|---|
11800/gRPC | Java、Python、Go 等原生 Agent 上报;受支持的 OTLP/gRPC 接收 | 应用到 OAP |
12800/HTTP | GraphQL 查询、健康检查及受支持的 HTTP 上报接口 | UI、管理网络及确有需要的 HTTP Agent |
8080/HTTP | UI | 管理网络或认证网关 |
1234/HTTP | OAP 自监控 Prometheus 指标 | 监控采集器 |
9200/HTTP(S) | Elasticsearch API | OAP 和存储管理网络 |
9411/HTTP | 可选 Zipkin HTTP 接收 | 仅启用该功能时使用 |
9412/HTTP | 可选 Zipkin 查询 | UI 到 OAP |
本文使用 OAP/UI 10.4.0、Java Agent 9.4.0 作为配置示例,Elasticsearch 8.17.4 作为单机实验存储。这些是固定示例版本,不代表最新版本或生产环境升级目标。
OAP 与 Agent 独立发布,不要求版本号完全一致。OAP 10.x 的兼容表包含 Java Agent 8.x/9.x,具体框架、JDK、语言运行时仍需分别核对 Agent 支持列表。OAP 容器自带运行时,不能把应用 JDK、Agent 支持的 JDK 和 OAP 的运行 JDK 混为一谈;10.4.0 的官方 OAP Dockerfile 使用 JRE 25 基础镜像,二进制部署应按对应发行版要求准备 JDK。
3. Docker Compose 部署
3.1 目录与宿主机准备
以下是单机实验配置,所有文件放在 /data/skywalking。建议为宿主机预留至少 4 核、8 GiB 内存和足够磁盘空间,实际需求受业务流量、采样率和保留期影响。
install -d -m 0755 /data/skywalking/config
install -d -m 0750 /data/skywalking/elasticsearch
chown 1000:0 /data/skywalking/elasticsearch
cd /data/skywalking
sysctl vm.max_map_count
Elasticsearch 8.17 实验环境的 vm.max_map_count 至少需要达到 262144;已经更高时保持原值。需要持久调整时:
if [ "$(sysctl -n vm.max_map_count)" -lt 262144 ]; then
printf 'vm.max_map_count=262144\n' > /etc/sysctl.d/90-skywalking-es.conf
sysctl -p /etc/sysctl.d/90-skywalking-es.conf
fi
启用 SELinux 的主机需为绑定挂载目录设置适当容器标签或使用合适的挂载标记,不能靠关闭 SELinux 解决目录权限问题。
3.2 docker-compose.yml
将下面内容保存到 /data/skywalking/docker-compose.yml:
name: skywalking
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.17.4
restart: unless-stopped
environment:
discovery.type: single-node
xpack.security.enabled: "false"
ES_JAVA_OPTS: "-Xms1g -Xmx1g"
volumes:
- /data/skywalking/elasticsearch:/usr/share/elasticsearch/data
healthcheck:
test:
- CMD-SHELL
- "curl -fsS 'http://localhost:9200/_cluster/health?wait_for_status=yellow&timeout=5s' >/dev/null"
interval: 10s
timeout: 10s
retries: 18
start_period: 40s
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
oap:
image: apache/skywalking-oap-server:10.4.0
restart: unless-stopped
depends_on:
elasticsearch:
condition: service_healthy
environment:
SW_STORAGE: elasticsearch
SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
SW_STORAGE_ES_INDEX_REPLICAS_NUMBER: "0"
SW_HEALTH_CHECKER: default
SW_TELEMETRY: prometheus
SW_CORE_RECORD_DATA_TTL: "3"
SW_CORE_METRICS_DATA_TTL: "7"
JAVA_OPTS: "-Xms1g -Xmx1g"
volumes:
- /data/skywalking/config:/skywalking/ext-config:ro
ports:
- "127.0.0.1:11800:11800"
- "127.0.0.1:12800:12800"
- "127.0.0.1:1234:1234"
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
ui:
image: apache/skywalking-ui:10.4.0
restart: unless-stopped
depends_on:
- oap
environment:
SW_OAP_ADDRESS: http://oap:12800
ports:
- "127.0.0.1:8080:8080"
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
实验存储没有对宿主机发布 9200。副本数 0 仅用于单节点验证,新建索引才按该配置创建;生产集群需要根据容错目标配置副本和节点数量。OAP 的 /skywalking/ext-config 会在启动时覆盖相应配置文件,只挂载需要覆盖的文件,不要用空目录遮住整个 /skywalking/config。
宿主机进程可以访问回环地址 127.0.0.1:11800;同一 Compose 网络中的应用使用 oap:11800。远程应用需要将映射改为宿主机的实际内网地址,并限制来源网络。容器中的 127.0.0.1 是容器自身,不能当作 OAP 地址。
3.3 启动与验收
cd /data/skywalking
docker compose config -q
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 elasticsearch oap ui
curl -fsS http://127.0.0.1:12800/healthcheck
OAP 初始化索引需要时间,刚启动时健康接口可能暂时失败。健康检查启用后,健康返回 200,不健康返回 503;未启用时可能返回 404。health checker 依赖 telemetry 模块,不能同时把 telemetry 关闭。
查询模块健康详情:
curl -fsS http://127.0.0.1:12800/graphql \
-H 'Content-Type: application/json' \
--data '{"query":"{checkHealth{score details}}"}'
score 为 0 表示健康,大于 0 表示存在不健康模块,负值表示尚未启动完成。GraphQL 的 HTTP 200 也可能包含 errors,需要检查响应正文。
检查存储与自监控指标:
docker compose exec -T elasticsearch \
curl -fsS 'http://localhost:9200/_cluster/health?pretty'
docker compose exec -T elasticsearch \
curl -fsS 'http://localhost:9200/_cat/indices?v'
curl -fsS http://127.0.0.1:1234/metrics -o /tmp/oap-metrics.txt
head -n 20 /tmp/oap-metrics.txt
本机浏览器访问 http://127.0.0.1:8080。服务器不在本机时,可以使用 SSH 隧道;下面的 22022 按实际 SSH 端口替换:
ssh -p 22022 -N -L 18080:127.0.0.1:8080 ops@skywalking.example.com
随后访问 http://127.0.0.1:18080。UI 能打开只说明前端可访问,完整验收还需要应用产生请求、出现服务指标并能查到 Trace。
4. Java、Spring Boot 与 Tomcat
4.1 安装 Java Agent
下载 Agent 9.4.0 发行包并校验 SHA-512:
install -d /data/skywalking/downloads
cd /data/skywalking/downloads
curl -fLO https://archive.apache.org/dist/skywalking/java-agent/9.4.0/apache-skywalking-java-agent-9.4.0.tgz
curl -fLO https://archive.apache.org/dist/skywalking/java-agent/9.4.0/apache-skywalking-java-agent-9.4.0.tgz.sha512
sha512sum -c apache-skywalking-java-agent-9.4.0.tgz.sha512
install -d /opt
tar -xzf apache-skywalking-java-agent-9.4.0.tgz -C /opt
test -f /opt/skywalking-agent/skywalking-agent.jar
保留 config、plugins 和 Agent 所需的其他目录,不能只复制一个 skywalking-agent.jar。应用用户需要读取 Agent 目录,并且能写入配置的 Agent 日志目录。
4.2 Spring Boot 启动
主机上的应用连接本机 Compose 暴露的端口:
export SW_AGENT_NAME='prod::orders-api'
export SW_AGENT_COLLECTOR_BACKEND_SERVICES='127.0.0.1:11800'
export SW_LOGGING_OUTPUT=CONSOLE
java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \
-jar /opt/orders-api/app.jar
也可以通过 JVM 系统属性配置:
java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.service_name='prod::orders-api' \
-Dskywalking.collector.backend_service=127.0.0.1:11800 \
-jar /opt/orders-api/app.jar
JVM 参数必须放在 -jar 前面。服务名、环境和分组统一规划,同一服务多个副本共用服务名;实例名可由 Agent 自动生成,Kubernetes 中可以使用 Pod 名。
4.3 Tomcat
在当前 Tomcat 实例的 $CATALINA_BASE/bin/setenv.sh 中加入:
export SW_AGENT_NAME='prod::web-tomcat'
export SW_AGENT_COLLECTOR_BACKEND_SERVICES='127.0.0.1:11800'
export CATALINA_OPTS="${CATALINA_OPTS:-} -javaagent:/opt/skywalking-agent/skywalking-agent.jar"
修改后重启 Tomcat。优先使用 CATALINA_OPTS,避免把 Agent 无差别加入所有 Java 子进程。直接运行 java -jar jenkins.war 时,也可以把 -javaagent 放在 -jar 前;观察 Jenkins 并不等于给其执行的所有构建任务自动添加 Agent。
4.4 插件与跨服务验证
Java Agent 的插件需要同时匹配框架类型和版本。可选插件按官方说明从 optional-plugins 放入 plugins,不要不加区分地启用全部插件。一次业务请求涉及的每个 Java 服务都要接入,数据库和 Redis 常见调用信息来自应用客户端插件,不要求在数据库进程里安装 Java Agent。
Dubbo 场景中分别为 Consumer 和 Provider 加载 Agent,使用不同服务名,再发起真实 RPC 调用。UI 中应能看到 Consumer → Provider 的关系和同一个 Trace。注册中心地址属于 Dubbo 应用配置,安装 Agent 不会替代 ZooKeeper/Nacos 的服务发现配置。
出现应用启动异常、类加载冲突或框架升级后没有 Span 时,先核对插件支持列表;不要通过降低整套应用的安全版本来迁就旧插件。
5. Docker 与 Kubernetes 应用接入
5.1 把 Agent 固定到应用镜像
构建上下文中准备经过校验的完整 skywalking-agent 目录和应用 app.jar:
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY skywalking-agent/ /opt/skywalking-agent/
COPY app.jar /app/app.jar
ENV SW_LOGGING_OUTPUT=CONSOLE
ENTRYPOINT ["java", "-javaagent:/opt/skywalking-agent/skywalking-agent.jar", "-jar", "/app/app.jar"]
这里的 JDK 21 是应用示例版本,应与应用和 Agent 支持范围一致。Agent 升级通过构建新镜像完成,不在容器启动时临时下载。
5.2 Deployment 配置
下面假定 OAP Service 名为 skywalking-oap,位于 observability 命名空间,并已把上面的应用镜像推送到实际仓库:
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-api
namespace: apps
spec:
replicas: 2
selector:
matchLabels:
app: orders-api
template:
metadata:
labels:
app: orders-api
spec:
containers:
- name: app
image: registry.example.com/orders-api:1.0.0
ports:
- name: http
containerPort: 8080
env:
- name: SW_AGENT_NAME
value: "prod::orders-api"
- name: SW_AGENT_INSTANCE_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
value: skywalking-oap.observability.svc:11800
- name: SW_LOGGING_OUTPUT
value: CONSOLE
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
memory: "1Gi"
---
apiVersion: v1
kind: Service
metadata:
name: orders-api
namespace: apps
spec:
selector:
app: orders-api
ports:
- name: http
port: 8080
targetPort: http
命名空间须提前存在。资源值只是起点,应根据业务与 Agent 的额外开销调整。配置应用自身的 readiness/liveness/startup probe 时,使用应用的真实健康接口,不能把 Agent 到 OAP 的连接状态当成业务存活条件。
kubectl -n apps get pods -l app=orders-api
kubectl -n apps logs deployment/orders-api --tail=100
kubectl -n observability get svc skywalking-oap
kubectl -n observability get endpointslices \
-l kubernetes.io/service-name=skywalking-oap
NetworkPolicy 需要允许应用到 OAP 的 11800/TCP;默认拒绝出站时还要允许 DNS。Token 通过 Secret 注入,不直接写入 Deployment 明文。
6. Python 与 Go
6.1 Python / Django
以下以 Python Agent 1.2.0 为例,其安装文档要求 Python 3.8+,实际 Python、Django 与依赖版本还要核对对应插件。建议使用项目虚拟环境,不向系统 Python 全局安装依赖:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install 'apache-skywalking==1.2.0'
export SW_AGENT_NAME='prod::orders-python'
export SW_AGENT_COLLECTOR_BACKEND_SERVICES='127.0.0.1:11800'
export SW_AGENT_PROTOCOL=grpc
sw-python run python manage.py runserver 127.0.0.1:8000 --noreload
manage.py 属于已有 Django 项目;该命令只用于开发验证。项目设置中明确配置 ALLOWED_HOSTS,不要直接设置为 ['*']。
生产使用已安装的 Gunicorn 时,按 Agent 的 prefork 支持启动;mysite.wsgi 替换为实际模块:
sw-python run -p gunicorn mysite.wsgi:application \
--workers 2 --bind 0.0.0.0:8000
Agent 不能只在 fork 前启动一套线程后就假定所有 worker 都正常上报。自动注入与手动 post_fork 启动方案选一种,不能重复初始化。
6.2 Go 编译期注入
只执行 go get 不会自动给一个现有二进制增加追踪。以下以 Go Agent 0.6.0 为例,需要下载并校验相同版本、匹配操作系统和 CPU 架构的 Agent 编译工具,将其放到 /opt/skywalking-go-agent;Go 工具链版本也要符合该 Agent 的支持范围。
在包含 main 包的源文件中导入:
import _ "github.com/apache/skywalking-go"
然后在项目根目录构建:
go get github.com/apache/skywalking-go@v0.6.0
go mod tidy
go build -toolexec=/opt/skywalking-go-agent -a -o orders-api .
export SW_AGENT_NAME='prod::orders-go'
export SW_AGENT_REPORTER_GRPC_BACKEND_SERVICE='127.0.0.1:11800'
./orders-api
编译工具版本必须与模块版本一致。-a 用于重新构建包,使编译注入生效;多 main 包项目应指定实际构建路径。Go 的后端变量是 SW_AGENT_REPORTER_GRPC_BACKEND_SERVICE,不能直接复制 Java 的后端环境变量。
7. OpenResty、网关与上下文传播
7.1 OpenResty Lua Agent
优先使用已集成 LuaJIT、常用 Lua 库的 OpenResty,避免把旧版 Lua、CJSON 和 Nginx 的手工编译日志直接拼成部署步骤。下面基于 skywalking-nginx-lua 1.0.1 的官方 API,假定完整库位于 /opt/skywalking-nginx-lua/lib,所需 Lua 依赖已安装,OAP 的 HTTP 上报接口可达。
在 nginx.conf 中配置:
events {
worker_connections 1024;
}
http {
lua_package_path "/opt/skywalking-nginx-lua/lib/?.lua;;";
lua_shared_dict tracing_buffer 20m;
init_worker_by_lua_block {
local buffer = ngx.shared.tracing_buffer
buffer:set("serviceName", "prod::edge-gateway")
buffer:set("serviceInstanceName", "edge-gateway-01")
buffer:set("includeHostInEntrySpan", false)
require("skywalking.util").set_randomseed()
require("skywalking.client"):startBackendTimer("http://127.0.0.1:12800")
skywalking_tracer = require("skywalking.tracer")
}
upstream orders_backend {
server 127.0.0.1:18081;
}
server {
listen 18080;
location / {
rewrite_by_lua_block {
skywalking_tracer:start("orders-api")
}
proxy_pass http://orders_backend;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
body_filter_by_lua_block {
if ngx.arg[2] then
skywalking_tracer:finish()
end
}
log_by_lua_block {
skywalking_tracer:prepareForReport()
}
}
}
}
OpenResty 和 OAP 不在同一主机或容器时,替换对应地址。网关实例名按部署副本区分,多个 worker 属于同一个网关实例。上游 18081 需要运行已接入 Agent 的实际业务服务,不能使用 Mock OAP 接口冒充采集成功。
openresty -t
openresty -s reload
curl -fsS http://127.0.0.1:18080/orders
module 'tablepool' not found、cjson.safe not found 属于 Lua 依赖或路径问题,先检查 OpenResty 的库路径和该 Agent 的依赖说明,不要随意复制不同版本的 .so。APISIX、Kong 等网关优先使用各自官方 SkyWalking 插件。
Nginx 性能指标与请求 Trace 是不同功能。只需要请求量、连接数和延迟时,可以使用 nginx-lua-prometheus → OpenTelemetry Collector → OAP,并配置对应 Nginx MAL 规则;仅启用 Exporter 不会生成跨服务 Trace。
7.2 跨进程、异步与浏览器
SkyWalking 原生 HTTP 追踪使用 sw8 等上下文头,不能把它当作普通请求 ID 自行拼接。代理若使用白名单清理请求头,需要保留对应追踪头;MQ 的 Producer/Consumer 插件需要支持当前客户端版本和消息属性传播。
自建线程池、回调或异步任务发生断链时,核对 Agent 插件是否覆盖执行模型;必要时使用 Toolkit 的上下文捕获和继续机制,不能只把 Trace ID 放进 ThreadLocal 或 MDC 就认为建立了父子关系。
浏览器观测通过 Browser Agent 收集页面性能和 JavaScript 错误。前后端串联还涉及被追踪域名、HTTP 请求头、CORS 允许头和后端 Agent 支持。生产通常通过网关仅开放必要采集路径,不能为了浏览器上报就把整个 OAP 12800 暴露公网。不要在页面中写 Agent Token 或管理凭据。
8. 日志与 Trace 关联
Java Logback 示例使用与 Agent 配套的 Toolkit。Maven 配置:
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>9.4.0</version>
</dependency>
logback-spring.xml 示例:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
%tid 依赖上述 Layout,不能直接放进任意默认编码器后就期待自动解析。未接入 Agent 或当前线程没有追踪上下文时,Trace ID 可能是 N/A。
把标准输出交给 Alloy、Fluent Bit 等采集器时,需要解析并保留 Trace ID 字段。日志采集与 Trace 上报是两条管道,输出 Trace ID 不会自动把日志发到 OAP;如需 OAP 原生日志查询,需要另行配置日志接收、解析与字段映射,或者使用 Toolkit 的 gRPC 日志 Appender。
SQL、URL、请求体和异常信息可能包含敏感数据。按需采集并脱敏,避免记录密码、Authorization、Cookie、完整用户资料和大体积报文。
9. OpenTelemetry 接入边界
OAP 10.4.0 可以接收 OTLP Trace、Metrics 和 Logs,但不同信号有不同分析规则。OTLP Trace 会转换成 Zipkin Trace,不能直接等同于 SkyWalking 原生 Agent Trace,也不会自动获得 Java Agent 的全部框架插件和原生拓扑分析能力。
在现有 Compose 中为 OAP 增加以下环境变量,启用 Trace 接收和 Zipkin 查询;本例不使用 Kafka:
environment:
SW_OTEL_RECEIVER: default
SW_OTEL_RECEIVER_ENABLED_HANDLERS: "otlp-traces,otlp-metrics,otlp-logs"
SW_RECEIVER_ZIPKIN: default
SW_ZIPKIN_KAFKA_COLLECTOR_ENABLED: "false"
SW_QUERY_ZIPKIN: default
UI 增加:
environment:
SW_ZIPKIN_ADDRESS: http://oap:9412
这些片段应合并到原有 environment,不能替换掉存储配置或 SW_OAP_ADDRESS。修改环境变量后执行 docker compose up -d 重新创建容器。
OTLP 客户端或 Collector 使用明确的 OTLP/gRPC 协议连接 oap:11800,不要默认向 12800/v1/traces 发送 OTLP/HTTP。资源属性至少设置 service.name,并规划环境与实例标识。Trace 使用 UI 的 /zipkin Lens 页面查询。
OTLP 指标需要匹配并启用对应 MAL/OTel 规则,例如 Nginx、OAP 自监控或数据库指标;任意自定义指标即使成功上传,也不一定自动变成可查询的内置仪表盘。已有 OTel Java Agent 的应用不要直接叠加 SkyWalking Java Agent,先评估重复埋点、上下文协议及性能影响。
10. 采样与数据保留
10.1 Agent 采样与 OAP 采样
| 配置位置 | 示例 | 含义 |
|---|---|---|
| Java Agent | SW_AGENT_SAMPLE=100 | 每个 Agent 每 3 秒的采样数量限制,不是 100% |
| Java Agent | SW_AGENT_SAMPLE=-1 | 关闭该数量限制,不是关闭 Agent |
| OAP | rate: 1000 | 服务端采样率 10%,精度为万分之一 |
| OAP | duration: 2000 | 强制保留超过 2000 ms 的慢 Segment |
OAP 服务端采样是在接收与指标分析之后减少 Trace 持久化,服务、实例、端点及拓扑指标仍按收到的数据分析;它不会减少 Agent 到 OAP 的上报带宽。Agent 侧已经丢弃的数据,OAP 无法恢复。
/data/skywalking/config/trace-sampling-policy-settings.yml 示例:
default:
rate: 1000
duration: 2000
services:
- name: "prod::payment-api"
rate: 10000
duration: 1000
OAP 默认 SW_FORCE_SAMPLE_ERROR_SEGMENT=true,可强制保留错误 Segment。强制保留错误或慢 Segment 不保证整个 Trace 的其他 Segment 都已保存;当故障导致大量慢请求时,实际保存比例可能显著高于基础采样率。
所有 OAP 节点应使用一致策略,避免同一 Trace 的片段因不同采样配置而缺失。静态配置修改后重启 OAP;需要不停机调整时使用该版本支持的动态配置机制。
10.2 TTL 与容量估算
本篇 Elasticsearch 示例使用:
environment:
SW_CORE_RECORD_DATA_TTL: "3"
SW_CORE_METRICS_DATA_TTL: "7"
单位是天。记录数据包括 Trace、日志、告警和慢 SQL 等;指标与元数据使用指标 TTL。BanyanDB 有自己的 TTL 配置,不能直接套用这两个 Core TTL 参数。
估算 Trace 存储时至少考虑:
每日 Trace 原始数据量
≈ 每秒完成的请求数 × 86400 × 实际采样率 × 每条 Trace 平均字节数
所需磁盘
≈ 每日索引实际增长量 × 保留天数 × (1 + 副本数) + 索引/合并余量
使用 ES 实际索引增长量评估磁盘更可靠;不要把序列化后的 Trace 大小直接当成磁盘占用。日志、指标、管理数据、分片开销和错误强制采样需要另外计入。监控磁盘水位、分片数量、堆使用率、GC、写入拒绝和查询延迟。
11. 告警规则与钉钉通知
11.1 指标含义
| 指标 | 含义 |
|---|---|
service_resp_time | 服务响应时间,单位 ms |
service_cpm | 每分钟调用次数,不是每秒请求数 |
service_sla | 成功率的内部万分比数值,10000 表示 100% |
service_percentile | 服务响应时间分位值,如 P95/P99 |
endpoint_resp_time | 端点响应时间,单位 ms |
成功率显示为百分比时需注意单位,告警中可使用 service_sla / 100 转换为百分数。错误判断受插件及 Segment 状态分析策略影响,不应只根据业务返回 HTTP 200 就推断一定成功。
11.2 alarm-settings.yml
将下面配置保存到 /data/skywalking/config/alarm-settings.yml。它会覆盖发行版自带规则;钉钉 URL 与签名密钥通过密钥管理系统注入部署文件,下面只使用占位值。
rules:
service_latency_rule:
expression: sum(service_resp_time > 1000) >= 3
period: 10
silence-period: 10
message: 'Service {name}: average response time exceeded 1000 ms in at least 3 minute buckets during the last 10 minutes'
tags:
level: WARNING
hooks:
- dingtalk.ops
service_success_rate_rule:
expression: sum((service_sla / 100) < 99) >= 3
period: 10
silence-period: 10
message: 'Service {name}: success rate below 99% in at least 3 minute buckets during the last 10 minutes'
tags:
level: CRITICAL
hooks:
- dingtalk.ops
hooks:
dingtalk:
ops:
text-template: |-
{"msgtype":"text","text":{"content":"SkyWalking Alarm: %s"}}
webhooks:
- url: "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
secret: "YOUR_SIGNING_SECRET"
规则 ID 以 _rule 结尾。period 是分钟窗口,sum(... ) >= 3 表示窗口内至少 3 个分钟数据点满足条件,不表示“3 次请求”或“连续 3 分钟”。silence-period 用于抑制重复通知。
表达式需要返回单值布尔结果,不能直接写 service_resp_time > 1000 就假定规则有效。服务级规则和端点级规则应分开;include-names 筛选的是对应实体名,服务分组前缀也需要匹配。
cd /data/skywalking
docker compose restart oap
docker compose logs --tail=100 oap
先确认 UI 中指标存在,再制造可控的慢请求或错误请求观察完整窗口。钉钉机器人还需满足自身的签名、关键词或来源限制。内置 hooks.dingtalk 可直接发送通知,不需要额外编译旧版 Java 转发程序。
自建 Webhook 时,按 SkyWalking 的告警 JSON 格式实现接收和转换;Alertmanager 的 API 与 SkyWalking Webhook 结构不同,不能直接把 URL 指向 Alertmanager 后就认为协议兼容。
12. 自监控与性能剖析
OAP 启用 SW_TELEMETRY=prometheus 后提供 1234/metrics。Prometheus 与 OAP 位于同一 Docker 网络时,可增加:
scrape_configs:
- job_name: skywalking-oap
scrape_interval: 15s
static_configs:
- targets: ["oap:1234"]
Prometheus 在宿主机运行时可使用 127.0.0.1:1234,远程采集则使用受控内网地址。优先关注 OAP 的 JVM 堆与 GC、接收/分析队列、存储写入失败、磁盘水位、查询延迟及 Agent 的上报异常。仅有 UI 仪表盘不能代替对 OAP 和存储自身的监控。
Trace 已定位到某个应用,但耗时集中在内部代码时,可以进一步创建有时间限制的 Profiling 任务,限定服务、实例和端点,再观察调用栈。Java Agent 的普通追踪剖析、基于 async-profiler 的剖析和 eBPF/Rover 功能有不同的运行时及权限要求,应按所用版本单独配置。先在低风险实例验证,控制采集时长与并发,不长期对全部实例开启高频剖析。
13. 生产部署、备份与升级
13.1 网络、认证与 TLS
| 通信链路 | 需要的措施 |
|---|---|
| 浏览器 → UI | HTTPS、统一身份认证或访问控制 |
| UI → OAP 查询 | 管理网络、来源限制,保护 12800 |
| Agent → OAP | 内网访问控制,按需启用 TLS/mTLS 和 Agent Token |
| OAP → Elasticsearch | TLS、证书校验、最小必要账户权限 |
Agent Token 只用于相应的采集认证,不会给 UI 或全部 HTTP 查询接口自动增加登录认证。
OAP 与 Java Agent 共享 Token 的配置变量分别是:
OAP: SW_AUTHENTICATION
Java Agent: SW_AGENT_AUTHENTICATION
Token 从 Secret 或部署系统注入,两端一致。跨不可信网络时同时启用 TLS,Token 本身不会加密传输。
Elasticsearch HTTPS 连接的 OAP 配置变量:
SW_STORAGE_ES_CLUSTER_NODES=es-01.internal:9200,es-02.internal:9200
SW_STORAGE_ES_HTTP_PROTOCOL=https
SW_ES_USER=skywalking
SW_ES_PASSWORD=<由密钥管理系统注入>
SW_STORAGE_ES_SSL_JKS_PATH=/skywalking/certs/es-truststore.jks
SW_STORAGE_ES_SSL_JKS_PASS=<由密钥管理系统注入>
将受信 CA 导入对应 Truststore,并挂载到 OAP。不要把 curl -k 或禁用证书验证作为长期方案。
13.2 多节点与高可用
生产 OAP 可部署多个节点,使用该版本支持的 Kubernetes、ZooKeeper、Consul 等集群发现方式,配置一致的存储、命名空间和采样策略。多台独立的 standalone OAP 放到负载均衡后,不等同于正确的 OAP 集群。
Agent 上报链路需要支持 gRPC/HTTP2,负载均衡器的空闲超时也需要匹配长连接。扩容后确认新节点被发现并接收流量,再根据接收、聚合和存储瓶颈扩容,不能只增加 UI 副本。
13.3 备份与升级
- 备份 Compose、OAP 覆盖配置、告警规则、镜像版本或摘要以及管理仪表盘。
- Elasticsearch 使用 Snapshot Repository 备份到独立存储;运行中复制数据目录不能替代一致性快照。
- 升级前阅读发行说明、存储迁移与 Agent 兼容说明,在测试环境回放典型请求。
- 灰度验证注册、Trace 串联、日志关联、告警与查询,再逐步切换实例。
- 存储格式或索引模板已变化时,不能假定降级镜像即可回滚;需要事先验证恢复路径。
停止单机实验环境使用 docker compose down,配置和绑定挂载的 ES 数据仍保留。清理历史记录优先使用 TTL,不要为了修复连接故障直接删除存储目录。
14. 排障步骤
| 现象 | 排查重点 |
|---|---|
| UI 空白、502 或查询失败 | UI 日志、SW_OAP_ADDRESS、12800、GraphQL 正文、网关超时 |
| 没有服务 | JVM 是否实际加载 Agent、Agent 目录与日志权限、服务名、DNS、11800、认证及 TLS |
| 有服务但没有 Trace | 是否产生真实请求、查询时间范围、插件支持、采样策略、忽略规则、写入异常 |
| Trace 跨服务断开 | 各跳 Agent、代理是否保留追踪头、MQ 属性、自建线程池上下文、不同协议之间的传播 |
UNAVAILABLE 或连接重试 | 地址、端口、DNS、Service Endpoints、NetworkPolicy、gRPC 代理与证书 |
PERMISSION_DENIED | Agent 与 OAP Token 是否一致、采集认证配置是否实际生效 |
UNIMPLEMENTED | Agent 使用的协议或功能是否超出 OAP 支持范围、是否连错服务 |
OAP 健康接口 503 | 模块健康详情、ES 连通性、认证、磁盘水位、索引写入与 OAP 内存 |
| ES 为 yellow | 检查是否仅为单节点无法分配副本,不要把 yellow 一概当作写入失败 |
ES 出现 read_only_allow_delete | 先解决磁盘水位,再确认相应版本的只读块恢复机制 |
日志出现 N/A | 当前线程是否有 Trace、Toolkit 与 Layout 是否加载、异步上下文是否传播 |
| 告警不发送 | 指标名与单位、MQE 表达式、分钟窗口、静默期、Hook 绑定、Webhook 网络与响应 |
| 服务或端点数量持续膨胀 | 服务名是否包含随机值、URL 是否模板化、标签是否混入用户 ID 或订单号 |
主机 Compose 排查:
cd /data/skywalking
docker compose ps
docker compose logs --since=10m --tail=200 oap
curl -fsS http://127.0.0.1:12800/healthcheck
ss -lnt | grep -E ':(11800|12800|8080|1234)\b'
docker compose exec -T elasticsearch \
curl -fsS 'http://localhost:9200/_cluster/health?pretty'
docker compose exec -T elasticsearch \
curl -fsS 'http://localhost:9200/_cat/allocation?v'
端口监听只证明进程打开了端口。排障顺序应是:Agent 已加载 → 地址和协议正确 → 认证及网络通过 → OAP 模块健康 → 存储可写 → 产生业务请求 → UI 按正确时间、服务和实例查询。跨主机时间不一致会影响时间范围和链路耗时分析,统一使用 NTP/chrony 同步。
最终验收至少包含一个实际业务入口、一次下游调用和一次可控错误:服务及实例出现,Trace ID 能跨服务关联,错误与延迟指标符合请求结果,日志能检索到相同 Trace ID,告警能够送达。
评论