SkyWalking 链路追踪
本文范围
很多团队第一次上 SkyWalking,不是输给 Trace、Span 这些概念,而是输给第一条链路没有跑通:Agent 明明加了,UI 里没有服务;服务出来了,Trace 查不到;Trace 出来了,日志里又没有 traceId。
这篇只解决一件事:把 SkyWalking 链路追踪从部署、接入、查看、定位慢调用,一直讲到生产治理和排障。Prometheus 指标体系、完整可观测性平台、业务 SQL 优化、网关灰度策略这些都不展开。它们会在排障边界里出现,但主角始终是链路追踪。
示例里默认三类环境:
- 学习验证环境:一台机器,用 Docker 或二进制包跑通
OAP + UI + 存储,再接入几个 Java 服务。 - 企业生产环境:至少两个 OAP 节点,独立存储,统一 UI 入口,服务名、采样、TTL、告警、日志关联都要落地。
- 中国大陆公网、企业内网、离线环境:不要假设 Docker Hub、GitHub、Apache 下载站、Maven Central 都能稳定访问,正式部署前要准备离线包、镜像、校验文件、私有仓库和回退方案。
这里要注意版本。写作时间是 2026-07-09,官方下载页显示 SkyWalking APM 最新稳定版本是 10.4.0,SkyWalking Java Agent 最新稳定版本是 9.6.0,BanyanDB Server 是 0.10.3。正式上线前再查一次官方下载页,不要把文章里的版本当成永久不变的版本锁。
前置条件
正式动手前,先把这些条件准备好:
- 已确认部署形态:本机验证、Docker Compose、二进制包、虚拟机集群,还是后续接入 K8S。本文不展开 Operator 深度部署。
- 已准备 OAP、UI 和存储后端。生产环境不要用 H2 或临时目录保存链路数据,要提前确定 BanyanDB、Elasticsearch 或其他官方支持存储。
- 网络端口已放通:Agent 到 OAP 的 gRPC
11800,UI 到 OAP 的 REST12800,UI 对外访问端口按网关或内网域名收口。 - Java Agent 已确认兼容当前 JDK、框架、中间件和启动方式,至少在灰度服务上验证过启动时间、CPU、内存和 GC 变化。
- 服务命名规则已确定,
service_name、实例名、环境和集群不要随发布批次随机变化。 - 已规划 Trace 明细、拓扑、指标和日志关联字段的保留周期,TTL 不是越长越好,要和磁盘预算一起算。
- 企业内网或离线环境已准备 APM 包、Java Agent 包、镜像、Maven 依赖、校验文件和回滚包。
- UI、OAP、存储和告警 Webhook 只在受控网络内开放,生产环境要考虑认证、访问审计和最小权限。
SkyWalking 到底帮你看什么
微服务排障最麻烦的地方,是一个请求会穿过很多服务。用户说“下单慢”,你可能要看 Gateway、用户服务、订单服务、库存服务、MySQL、Redis、消息队列、第三方支付接口。只看单个服务日志,很容易越查越乱。
SkyWalking 做的事很直接:把同一次请求经过的服务和调用按时间顺序串起来,告诉你每一段花了多久,哪一段报错,调用关系从哪里开始,到哪里结束。
一个简单链路长这样:
浏览器
-> Spring Cloud Gateway
-> mall-user /api/users/1
-> mall-order /api/orders?userId=1
-> MySQL SELECT orders
-> Redis GET user:1接入成功后,访问 UI 应该能看到四类东西:
- 拓扑图里有
mall-gateway -> mall-user -> mall-order -> MySQL。 - 端点列表里有
/api/users/{id}、/api/orders这类接口。 - 追踪页面能打开单条 Trace,里面有一段一段的 Span 瀑布图。
- 业务日志里有同一个 traceId,可以从 UI 回查到多服务日志。
如果这四件事有一件缺了,就别急着接更多服务,先把这条最小链路查通。
Trace、Segment、Span 先会用
这些名字不用背概念,先按排障视角理解。
| 对象 | 可以理解成 | 排障时看什么 |
|---|---|---|
| Trace | 一次完整请求 | 从入口到所有下游的完整路径 |
| Segment | 一个服务进程上报的一段 Trace | 某个 JVM 里采集到的一组 Span |
| Span | 一次具体调用或执行片段 | 谁慢、谁报错、谁调用了谁 |
| EntrySpan | 请求进入当前服务 | Controller、RPC Provider、网关入口 |
| ExitSpan | 当前服务调用外部 | Feign、HTTP Client、Dubbo Consumer、JDBC、Redis、MQ Producer |
| LocalSpan | 当前服务内部片段 | 自定义业务方法、关键计算步骤 |
| Service | 逻辑服务名 | 一般对应 spring.application.name 或 Agent 服务名 |
| Service Instance | 服务实例 | 一个 JVM、一个容器、一个 Pod |
| Endpoint | 接口或方法 | HTTP URI、RPC 方法、gRPC 方法 |
现场排障时,我通常先问这几个问题:
- UI 里有没有 Service?没有就先查 Agent 是否启动、OAP 是否可达、服务名是否配置。
- 有 Service 但没有 Trace?先查有没有真实请求、入口插件是否生效、时间范围是否选错、采样是否保存。
- Trace 到一半断了?先查下游服务是否也接了 Agent,再看 Gateway、Feign、MQ、线程池这些边界。
- 日志 traceId 是
N/A?先查日志 toolkit、layout、异步线程和 Agent 启动状态。
这几个问题能覆盖大部分第一次接入失败。
OAP、UI、Agent 怎么连
SkyWalking 最小闭环由四部分组成:Java Agent 采集,OAP 接收和分析,Storage 保存数据,UI 查询展示。
先记住一句话:Agent 连 11800,UI 连 12800,人访问 UI 的 Web 端口通常是 8080。
| 端口 | 谁提供 | 谁来访问 | 用途 |
|---|---|---|---|
11800 | OAP | Java Agent | gRPC 上报 Trace、指标等数据 |
12800 | OAP | UI | HTTP REST/GraphQL 查询 |
8080 | UI | 浏览器 | SkyWalking 页面 |
这里最常见的错法是把 Agent 配到 12800,或者把 UI 配到 11800。端口一错,命令看起来都对,数据就是不上来。
排障时按这个顺序查:
# 1. 应用进程有没有带 Agent
ps -ef | grep java | grep skywalking-agent
# 2. 应用机器能不能连 OAP 上报端口
nc -vz oap.example.com 11800
# 3. UI 机器能不能连 OAP 查询端口
nc -vz oap.example.com 12800
# 4. OAP 本机是否监听端口
ss -lntp | egrep '11800|12800'执行后应该看到 Java 进程里有 -javaagent,nc 显示连接成功,OAP 机器上能看到 11800 和 12800 监听。任何一步不对,就先停在那里查,不要跳到 UI 里乱点。
中国大陆、内网、离线环境先准备
SkyWalking 真正落生产时,第一关经常不是配置,而是制品能不能稳定拿到。内网环境不要让业务容器启动时临时去外网拉 Agent、插件、镜像或 Maven 依赖,这种做法在生产上迟早踩坑。
一般需要提前准备这些东西:
- SkyWalking APM 二进制包,包含 OAP 和 UI。
- SkyWalking Java Agent 包。
- 存储组件制品,例如 BanyanDB、Elasticsearch 或 OpenSearch。
- Maven 依赖,例如
apm-toolkit-trace、apm-toolkit-logback-1.x、apm-toolkit-log4j-2.x。 - 镜像包和私有镜像仓库,例如 Harbor 或云厂商企业镜像仓库。
- 校验文件,例如
.sha512、.asc,以及企业内部制品清单。
外网机器下载完,先做校验:
sha512sum -c apache-skywalking-apm-10.4.0-bin.tar.gz.sha512
sha512sum -c apache-skywalking-java-agent-9.6.0.tgz.sha512看到 OK 才继续往内网传。如果这里校验失败,不要手工改文件名蒙混过去,重新下载或换可信下载节点。
有 GPG 流程的团队,再验签:
gpg --verify apache-skywalking-apm-10.4.0-bin.tar.gz.asc apache-skywalking-apm-10.4.0-bin.tar.gz
gpg --verify apache-skywalking-java-agent-9.6.0.tgz.asc apache-skywalking-java-agent-9.6.0.tgz镜像离线流转可以这样做:
docker pull apache/skywalking-oap-server:10.4.0
docker pull apache/skywalking-ui:10.4.0
docker save apache/skywalking-oap-server:10.4.0 -o skywalking-oap-server-10.4.0.tar
docker save apache/skywalking-ui:10.4.0 -o skywalking-ui-10.4.0.tar
sha512sum skywalking-oap-server-10.4.0.tar skywalking-ui-10.4.0.tar > skywalking-images.sha512传到内网后先校验,再导入:
sha512sum -c skywalking-images.sha512
docker load -i skywalking-oap-server-10.4.0.tar
docker load -i skywalking-ui-10.4.0.tar如果企业内有 Harbor,一般再打内部标签:
docker tag apache/skywalking-oap-server:10.4.0 harbor.example.com/ops/skywalking-oap-server:10.4.0
docker tag apache/skywalking-ui:10.4.0 harbor.example.com/ops/skywalking-ui:10.4.0
docker push harbor.example.com/ops/skywalking-oap-server:10.4.0
docker push harbor.example.com/ops/skywalking-ui:10.4.0生产部署时业务服务只引用内网镜像地址。这样做的好处很朴素:上线窗口里不赌公网,不赌镜像站,不赌 DNS。
部署方式怎么选
先不要一上来就追求“大而全”。SkyWalking 要先跑通,再治理,再高可用。
| 场景 | 推荐方式 | 重点 |
|---|---|---|
| 本地学习 | 官方 quickstart 或 Docker Compose | 先看懂端口、服务、Trace |
| 单台测试服务器 | Docker Compose | 便于清理和复现 |
| 传统虚拟机生产 | 二进制包 + systemd,或企业 Compose | 重点是端口、存储、日志、备份 |
| K8S 生产 | Helm 或 Operator | 这里不展开 K8S,只讲接入边界 |
| 完全离线 | 离线包 + 私有镜像仓库 + Maven 私服 | 所有制品提前入库 |
生产上不要使用 latest 镜像,不要用 H2 或临时目录承载长期数据,也不要把 OAP、UI、存储直接暴露到公网。
先用 Docker 跑通最小环境
公网可访问时,可以先用官方 quickstart 验证 OAP、UI 和存储是否能跑起来。Linux、macOS、WSL 执行:
bash <(curl -sSL https://skywalking.apache.org/quickstart-docker.sh)Windows PowerShell 执行:
Invoke-Expression ([System.Text.Encoding]::UTF8.GetString((Invoke-WebRequest -Uri https://skywalking.apache.org/quickstart-docker.ps1 -UseBasicParsing).Content))脚本会让你选择存储类型,然后启动后端集群。这里要注意,quickstart 适合学习验证,不适合生产直接照搬。生产环境要把镜像版本、数据目录、网络、安全策略和存储配置都展开成明确配置。
启动后先看容器:
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}"应该能看到 OAP、UI 和存储相关容器,并且状态是 Up。如果容器反复重启,先看日志:
docker logs --tail=200 skywalking-oap
docker logs --tail=200 skywalking-ui再看端口:
ss -lntp | egrep '11800|12800|8080'这里应该看到三个端口。11800 没有,Agent 不可能上报;12800 没有,UI 查不到 OAP;8080 没有,浏览器访问不到 UI。
验证 UI:
curl -I http://127.0.0.1:8080/能返回 200、302 或静态资源响应,都说明 Web 入口基本通了。然后浏览器访问:
http://服务器IP:8080/访问后应该看到 SkyWalking UI。刚打开时没有业务服务是正常的,因为还没有 Java 应用上报数据。
验证 OAP 查询端口:
curl -I http://127.0.0.1:12800/验证 OAP 上报端口:
nc -vz 127.0.0.1 1180011800 是 gRPC,不要用普通 HTTP GET 判断业务是否正常。这里用 nc 只是确认 TCP 能连通。
如果要清理 quickstart 环境:
docker compose --project-name=skywalking-quickstart down二进制包部署
传统虚拟机或物理机上,我更喜欢用二进制包加 systemd 托管。这样日志、端口、进程、用户权限都比较清楚。
先准备用户和目录。如果没有 skywalking 用户就新建:
id skywalking || sudo useradd -r -s /sbin/nologin skywalking
sudo mkdir -p /opt/skywalking解压:
sudo tar -xf apache-skywalking-apm-10.4.0-bin.tar.gz -C /opt/skywalking --strip-components=1
sudo chown -R skywalking:skywalking /opt/skywalking看目录:
ls -1 /opt/skywalking一般会看到这些目录:
bin
config
logs
webappOAP 主配置通常在:
/opt/skywalking/config/application.ymlUI 配置通常在:
/opt/skywalking/webapp/webapp.yml先手工启动一次,确认包和 Java 环境没问题:
sudo -u skywalking /opt/skywalking/bin/oapService.sh
sudo -u skywalking /opt/skywalking/bin/webappService.sh看日志:
tail -f /opt/skywalking/logs/skywalking-oap-server.log
tail -f /opt/skywalking/logs/webapp.log看进程和端口:
jps -lv | grep -i skywalking
ss -lntp | egrep '11800|12800|8080'如果这里看不到 11800,先查 OAP 日志;如果 8080 被占用,就改 UI 端口或停掉占用进程。
生产上不要靠手工命令守着进程,交给 systemd。
OAP 单元示例:
[Unit]
Description=Apache SkyWalking OAP
After=network-online.target
Wants=network-online.target
[Service]
User=skywalking
Group=skywalking
WorkingDirectory=/opt/skywalking
Environment="SW_STORAGE=banyandb"
ExecStart=/opt/skywalking/bin/oapService.sh
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=10
LimitNOFILE=65535
[Install]
WantedBy=multi-user.targetUI 单元示例:
[Unit]
Description=Apache SkyWalking UI
After=network-online.target skywalking-oap.service
Wants=network-online.target
[Service]
User=skywalking
Group=skywalking
WorkingDirectory=/opt/skywalking
ExecStart=/opt/skywalking/bin/webappService.sh
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target保存后启用:
sudo systemctl daemon-reload
sudo systemctl enable --now skywalking-oap
sudo systemctl enable --now skywalking-ui
sudo systemctl status skywalking-oap --no-pager
sudo systemctl status skywalking-ui --no-pager状态应该是 active (running)。如果不是,直接看日志,不要只盯着 systemd 的一行失败信息:
journalctl -u skywalking-oap -n 200 --no-pager
journalctl -u skywalking-ui -n 200 --no-pager存储后端和数据保留
SkyWalking 的存储是可插拔的。当前官方文档里默认选择器是 banyandb,同时也支持 Elasticsearch、OpenSearch、MySQL、PostgreSQL 等。
| 存储 | 适合场景 | 注意点 |
|---|---|---|
| BanyanDB | 新部署、链路追踪主场景、希望降低资源成本 | SkyWalking 原生场景更贴合,版本和部署方式要跟官方文档校准 |
| Elasticsearch / OpenSearch | 已有搜索集群、团队熟悉 ES 运维、大规模检索 | 成本高,分片、磁盘水位、保留周期都要治理 |
| MySQL / PostgreSQL | 中小规模、低采样、简单验证 | 不适合高吞吐 Trace 明细长期全量写入 |
| H2 | 本地演示 | 不适合生产 |
BanyanDB 配置方向:
storage:
selector: ${SW_STORAGE:banyandb}
banyandb:
targets: ${SW_STORAGE_BANYANDB_TARGETS:127.0.0.1:17912}这里要注意,容器里的 127.0.0.1 指的是容器自己,不是宿主机,也不是另一个容器。Compose 网络里应该写服务名,例如:
SW_STORAGE_BANYANDB_TARGETS: "banyandb:17912"Elasticsearch 配置方向:
storage:
selector: ${SW_STORAGE:elasticsearch}
elasticsearch:
namespace: ${SW_NAMESPACE:"skywalking"}
clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:elasticsearch:9200}改完存储配置后重启 OAP,然后验证写入。
ES 常用检查:
curl -s http://elasticsearch:9200/_cluster/health?pretty
curl -s http://elasticsearch:9200/_cat/indices/skywalking*?v
curl -s http://elasticsearch:9200/_cat/allocation?v如果 OAP 日志里出现索引创建失败、写入失败、磁盘水位过高,UI 里可能表现为:服务有了,指标有一部分,Trace 明细查不到,历史数据断档。
保留周期不要拍脑袋。官方 TTL 文档里把数据分成两类:Record 包含 traces、logs、alarm 等,常用 recordDataTTL 控制;Metrics 包含 service、instance、endpoint、topology 等指标和元数据,常用 metricsDataTTL 控制。
常见方向:
core:
default:
recordDataTTL: ${SW_CORE_RECORD_DATA_TTL:3}
metricsDataTTL: ${SW_CORE_METRICS_DATA_TTL:7}这里的单位是天。BanyanDB 有自己的 TTL 机制,使用 BanyanDB 时要看对应存储配置,不要只改这两个通用参数。
生产上一般这样定:
- Trace 明细保留 3 到 7 天,故障高发期临时延长。
- 指标聚合保留 7 到 30 天,用来看趋势和容量。
- 告警记录保留 30 到 90 天,用于复盘。
- 日志主体交给日志系统,SkyWalking 日志上报只保留排障窗口。
Java Agent 接入
Java 服务接入 SkyWalking,最常用的方式是加 -javaagent。它不要求你先改业务代码,但要求启动参数、服务名、OAP 地址都正确。
先把 Agent 放到应用机器。示例目录按企业规范可以调整:
sudo mkdir -p /opt/skywalking-agent
sudo tar -xf apache-skywalking-java-agent-9.6.0.tgz -C /opt
sudo chown -R app:app /opt/skywalking-agent看一下 Agent 目录:
ls -1 /opt/skywalking-agent一般会看到:
activations
config
logs
optional-plugins
plugins
skywalking-agent.jar最小启动命令:
java \
-javaagent:/opt/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=mall-user \
-Dskywalking.collector.backend_service=10.10.10.20:11800 \
-jar mall-user.jar这条命令解决三件事:
-javaagent告诉 JVM 启动时加载 SkyWalking Agent。service_name告诉 SkyWalking 这个进程在 UI 里叫什么。backend_service告诉 Agent 数据上报到哪个 OAP11800。
这里要注意 -javaagent 必须放在 -jar 前面。放在后面,JVM 不会按 Java Agent 处理。
启动后马上验证:
ps -ef | grep mall-user | grep javaagent
ls -l /opt/skywalking-agent/logs
grep -i "skywalking" /opt/skywalking-agent/logs/*.log如果 ps 看不到 -javaagent,说明启动参数没进进程;如果 Agent 日志里报连不上 OAP,就查 11800、防火墙、安全组和地址配置。
环境变量方式也常见:
export SW_AGENT_NAME=mall-user
export SW_AGENT_COLLECTOR_BACKEND_SERVICES=10.10.10.20:11800
export SW_AGENT_SPAN_LIMIT=300
java -javaagent:/opt/skywalking-agent/skywalking-agent.jar -jar mall-user.jar生产上建议统一一种写法。不要一半服务用 -Dskywalking.*,一半服务用 SW_AGENT_*,出了问题很难判断最终生效的是哪一套。
systemd 接入模板:
[Unit]
Description=mall-user service
After=network-online.target
Wants=network-online.target
[Service]
User=app
Group=app
WorkingDirectory=/data/apps/mall-user
Environment="SW_AGENT_NAME=mall-user"
Environment="SW_AGENT_COLLECTOR_BACKEND_SERVICES=10.10.10.20:11800,10.10.10.21:11800"
ExecStart=/usr/bin/java -javaagent:/opt/skywalking-agent/skywalking-agent.jar -Xms1g -Xmx1g -jar mall-user.jar
Restart=on-failure
RestartSec=10
StandardOutput=append:/data/logs/mall-user/stdout.log
StandardError=append:/data/logs/mall-user/stderr.log
[Install]
WantedBy=multi-user.target改完后:
sudo systemctl daemon-reload
sudo systemctl restart mall-user
sudo systemctl status mall-user --no-pager
ps -ef | grep mall-user | grep javaagent如果没有就新建日志目录。如果目录权限不对,应用可能能启动,但日志写不进去:
sudo mkdir -p /data/logs/mall-user
sudo chown -R app:app /data/logs/mall-userDocker 镜像里内置 Agent:
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY target/mall-user.jar /app/mall-user.jar
COPY skywalking-agent /opt/skywalking-agent
ENV JAVA_TOOL_OPTIONS="-javaagent:/opt/skywalking-agent/skywalking-agent.jar"
ENV SW_AGENT_NAME="mall-user"
ENV SW_AGENT_COLLECTOR_BACKEND_SERVICES="skywalking-oap:11800"
ENTRYPOINT ["java", "-jar", "/app/mall-user.jar"]运行时挂载 Agent:
services:
mall-user:
image: harbor.example.com/mall/mall-user:1.0.0
environment:
JAVA_TOOL_OPTIONS: "-javaagent:/opt/skywalking-agent/skywalking-agent.jar"
SW_AGENT_NAME: "mall-user"
SW_AGENT_COLLECTOR_BACKEND_SERVICES: "skywalking-oap:11800"
volumes:
- /opt/skywalking-agent:/opt/skywalking-agent:ro容器里最容易写错的是 127.0.0.1:11800。除非 OAP 和业务进程在同一个容器里,否则这个地址一定不对。Compose 里写服务名,K8S 里写 Service DNS,虚拟机里写 OAP 内网 IP 或负载均衡地址。
服务名配置不要乱
SkyWalking UI 里的服务名,后面排障会天天用。名字一乱,拓扑就乱,日志也乱。
Spring 应用一般有:
spring:
application:
name: mall-orderAgent 里也建议保持一致:
-Dskywalking.agent.service_name=mall-order不要出现 Nacos 里叫 mall-order-service,SkyWalking 里叫 order-prod-v1,日志里又叫 order-server。看起来只是名字问题,真正排障时会浪费很多时间。
生产命名建议:
- 一个逻辑服务一个稳定名字,例如
mall-order。 - 不把 IP、容器 ID、版本号写进服务名,这些属于实例维度或标签维度。
- 多环境可以用 namespace、集群名或部署环境隔离,不要让测试和生产混在一个服务名下。
- 服务改名要当成一次可观测性变更,提前通知研发和运维。
Nacos、Gateway、微服务边界
Nacos 负责注册发现和配置管理,SkyWalking 负责链路追踪。服务注册到 Nacos,不等于会自动出现在 SkyWalking UI。
每个 Java 服务仍然要接 Agent:
java \
-javaagent:/opt/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=mall-order \
-Dskywalking.collector.backend_service=10.10.10.20:11800 \
-jar mall-order.jar如果 Nacos 里服务正常,SkyWalking UI 里没有,按 Agent 上报问题查,不要去 Nacos 控制台里找 SkyWalking 配置。
Spring Cloud Gateway 也是一个独立服务,也要接 Agent:
java \
-javaagent:/opt/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=mall-gateway \
-Dskywalking.collector.backend_service=10.10.10.20:11800 \
-jar mall-gateway.jarGateway 不显示时先查:
ps -ef | grep mall-gateway | grep javaagent
ls /opt/skywalking-agent/plugins | grep -i gateway
ls /opt/skywalking-agent/optional-plugins | grep -i gateway如果 UI 里能看到后端服务,但看不到 Gateway,一般是 Gateway 进程没带 Agent、插件版本不匹配,或者对应插件在 optional-plugins 里没有启用。
Feign、RestTemplate、WebClient 这些客户端调用能否自动形成 ExitSpan,取决于 Agent 插件和框架版本。
验证方式很简单:
curl -H "Content-Type: application/json" http://gateway.example.com/api/users/1
grep "/api/orders" /data/logs/mall-order/app.log然后到 UI 追踪页面,按最近 15 分钟查这次请求。如果日志里有下游请求,但 Trace 里没有下游 Span,通常是客户端插件没生效、上下文没透传、版本不匹配,或者采样没保存这条 Trace。
MQ 和异步场景要再小心一点:
- Producer 和 Consumer 都要接 Agent。
- Kafka、RocketMQ、RabbitMQ 等插件要确认支持版本。
- 异步消费链路不要和同步 HTTP 总耗时混为一谈。
- 插件不支持时,要用 toolkit 或业务 header 辅助透传。
- 线程池切换后 traceId 可能丢,要用跨线程 toolkit 或统一封装任务提交。
跑通第一条链路
不要一开始就把几十个服务全接上。先用三个服务验证:
mall-gateway -> mall-user -> mall-order三个服务都加 Agent:
COMMON_AGENT="-javaagent:/opt/skywalking-agent/skywalking-agent.jar"
OAP="-Dskywalking.collector.backend_service=10.10.10.20:11800"
java $COMMON_AGENT -Dskywalking.agent.service_name=mall-gateway $OAP -jar mall-gateway.jar
java $COMMON_AGENT -Dskywalking.agent.service_name=mall-user $OAP -jar mall-user.jar
java $COMMON_AGENT -Dskywalking.agent.service_name=mall-order $OAP -jar mall-order.jar打几次真实请求:
for i in {1..20}; do
curl -s http://gateway.example.com/api/users/1 >/dev/null
sleep 1
done访问 UI 后应该看到:
- 服务列表出现
mall-gateway、mall-user、mall-order。 - 拓扑图出现 Gateway 到 User,再到 Order。
- 端点里有
/api/users/{id}或对应接口。 - 追踪页面能搜到单条 Trace。
- Trace 瀑布图里有每个服务的 Span 和耗时。
如果没有,就按顺序查:
ps -ef | egrep 'mall-gateway|mall-user|mall-order' | grep javaagent
nc -vz 10.10.10.20 11800
tail -n 200 /opt/skywalking-agent/logs/*.log
tail -n 200 /opt/skywalking/logs/skywalking-oap-server.log第一条链路跑通后,再批量接入其他服务。
一次请求的 Trace / Span 链路图
做 SkyWalking 接入评审时,最有用的不是背 Trace、Segment、Span 定义,而是把一次请求从入口服务到 OAP、存储、UI 和日志关联画完整。这样上线前能检查 -javaagent、service_name、backend_service、采样和 TTL,排障时也能判断是 Agent 没生效、上下文没透传,还是 OAP / Storage 写入出了问题。
上线检查时按图逐段验证:应用进程里能看到 -javaagent,Agent 配置的 -Dskywalking.agent.service_name 稳定,-Dskywalking.collector.backend_service 指向 OAP 11800,UI 能通过 OAP 12800 查到 Trace,日志能用同一个 traceId 回查。若 UI 有服务但没有单条 Trace,先看采样、时间范围和存储 TTL;若 Trace 到一半断了,重点查下游是否接 Agent、插件是否支持、异步线程或 MQ 是否做了上下文透传。
UI 里怎么查
SkyWalking UI 常用入口不多,排障时别乱点。
| 页面 | 看什么 | 常用动作 |
|---|---|---|
| 仪表盘 | 服务负载、成功率、延迟、Apdex | 判断是全局慢还是单服务慢 |
| 拓扑 | 服务依赖和调用方向 | 找入口、下游、异常边 |
| 服务 | 单个服务指标 | 看 RT、成功率、实例差异 |
| 实例 | JVM 或容器实例 | 判断是否某个实例异常 |
| 端点 | API 或 RPC 方法 | 找慢接口和失败接口 |
| 追踪 | 单条 Trace 瀑布图 | 定位慢 Span、异常 Span |
| 告警 | 规则触发记录 | 验证故障窗口和告警收敛 |
慢接口定位路径:
仪表盘发现延迟升高
-> 服务维度确认哪个服务慢
-> 端点维度确认哪个接口慢
-> 追踪页面筛选慢 Trace
-> 打开瀑布图看最慢 Span
-> 用 traceId 回查日志异常链路定位路径:
告警或日志发现错误
-> UI 按服务、端点、时间范围筛选失败 Trace
-> 打开 Trace 看错误 Span
-> 看 Span tags、异常堆栈、下游响应码
-> 用 traceId 查多服务日志
-> 修复后用同一路径验证成功率这里要注意时间范围。很多人查不到 Trace,不是没上报,而是 UI 时间选在了错误窗口。
慢接口定位实战
假设用户反馈 /api/users/1 偶发超过 3 秒。先不要直接怀疑数据库,也不要先改代码,先用链路把慢点找出来。
第一步,在 UI 里看服务和端点:
- 时间范围选故障窗口,例如最近 30 分钟。
- 进入
mall-user服务。 - 看
Endpoint Avg Response Time、Endpoint Response Time Percentile、Slow Endpoints。 - 找到
/api/users/{id}。
第二步,查慢 Trace:
- 进入追踪页面。
- 服务选择
mall-user。 - 端点选择
/api/users/{id}。 - 耗时下限设置为
3000ms。 - 打开最慢的一条 Trace。
第三步,看瀑布图。假设看到:
mall-gateway /api/users/1 3050ms
mall-user /api/users/{id} 2960ms
Redis GET user:1 10ms
mall-order /api/orders?userId=1 2700ms
MySQL SELECT order 2600ms这个结果说明入口慢不是 Gateway,也不是 Redis,而是 mall-order 查 MySQL 慢。SkyWalking 的任务到这里就完成了:它把慢点定位到具体 Span。接下来才进入慢 SQL、索引、锁等待、连接池这些专题。
第四步,用 traceId 查日志:
grep "TRACE_ID_FROM_UI" /data/logs/mall-user/app.log
grep "TRACE_ID_FROM_UI" /data/logs/mall-order/app.log如果日志里没有 traceId,先补日志关联。不然链路上知道哪里慢,日志里却看不到当时的用户、订单、租户、参数,排障还是断的。
跨服务调用分析
跨服务调用不要只看“有没有服务”,要看调用方向和耗时是否符合真实业务。
正常情况下,拓扑应该和调用关系一致:
mall-gateway -> mall-user -> mall-order
mall-user -> Redis
mall-order -> MySQL如果拓扑里多了一条奇怪调用,先查这个服务是否真的发起了请求:
grep "mall-order" /data/logs/mall-user/app.log
grep "http" /data/logs/mall-user/app.log如果业务日志里没有这次调用,可能是服务名配置混乱、历史服务残留、时间范围过大,或者多个环境共用了同一个 SkyWalking namespace。
如果真实调用存在,但 UI 里没有下游,按这几项查:
ps -ef | grep mall-order | grep javaagent
grep -i "plugin" /opt/skywalking-agent/logs/*.log
grep "TRACE_ID_FROM_UPSTREAM" /data/logs/mall-order/app.log一般原因:
- 下游服务没有接 Agent。
- 下游服务名配置成了另一个名字,看起来像断链。
- Feign、Gateway、MQ 插件版本不匹配。
- 异步线程或 MQ 消息没有传播上下文。
- 采样没有保存这条 Trace 明细。
异常链路分析
异常链路先分三类,不要一上来就把所有错误都当业务异常:
- 当前服务代码抛异常。
- 下游返回错误或超时。
- 链路本身断了,看不到真正错误点。
排查路径:
UI 失败 Trace
-> 找红色或错误 Span
-> 判断错误发生在 EntrySpan、ExitSpan 还是 LocalSpan
-> EntrySpan 错误多半是当前接口处理失败
-> ExitSpan 错误多半是调用下游失败
-> LocalSpan 错误多半是自定义业务片段失败常见现象:
| 现象 | 可能原因 | 怎么验证 |
|---|---|---|
| 当前服务 EntrySpan 报错 | Controller、Filter、业务异常 | 查当前服务同一 traceId 日志 |
| ExitSpan HTTP 500 | 下游服务返回 500 | 查下游服务同一 traceId 日志 |
| ExitSpan 超时 | 下游慢、网络慢、连接池耗尽 | 看 Span 耗时、客户端超时配置、下游实例 |
| Trace 到某服务后断掉 | 下游没接 Agent 或上下文没透传 | 看下游 JVM 参数、插件、请求头 |
| UI 没失败 Trace 但日志有异常 | 异常未被插件捕获、采样未保存、时间范围不对 | 放宽筛选,查 Agent/OAP 日志 |
排障时常用:
grep "TRACE_ID_FROM_UI" /data/logs/*/*.log
grep -i "exception\|error\|timeout" /data/logs/mall-order/app.log看完链路和日志,再决定是修当前服务、下游服务、网络还是依赖组件。
日志 traceId 关联
链路追踪和日志必须打通。只有 Trace 没有业务日志,很难知道当时的用户、订单、租户和参数;只有日志没有 Trace,又很难知道跨服务路径。
logback 接入先加依赖:
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>9.6.0</version>
</dependency>logback-spring.xml 示例:
<configuration scan="true" scanPeriod="5 seconds">
<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>如果项目统一用 MDC,可以用:
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>启动后打一次请求:
curl http://gateway.example.com/api/users/1
grep "api/users" /data/logs/mall-user/app.log日志里应该能看到 traceId。如果看到 TID: N/A,一般是当前日志不在活跃 Trace 上下文中、Agent 没生效、layout 没换成 SkyWalking toolkit,或者异步线程丢了上下文。
代码里读取 traceId 需要:
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>9.6.0</version>
</dependency>读取方式:
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
String traceId = TraceContext.traceId();
log.info("traceId={}", traceId);也可以把 traceId 返回给前端或客服系统:
response.setHeader("X-Trace-Id", TraceContext.traceId());这样用户反馈问题时,客服能拿到 X-Trace-Id,研发可以直接查链路和日志。
自定义 Span 和跨线程
默认 Agent 会采集常见框架和中间件。只有关键业务边界看不清时,才考虑加自定义 Span。
示例:
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Trace;
@Trace
@Tag(key = "orderId", value = "arg[0]")
public OrderDetail loadOrderDetail(Long orderId) {
return orderRepository.findDetail(orderId);
}这里要注意,不要把每个普通方法都加 @Trace。Span 太多会增加采集、传输、存储和 UI 阅读成本,最后排障的人看到的是一片噪声。
异步线程里 traceId 丢失很常见。原因是 Trace 上下文和 MDC 通常依赖线程上下文,线程切换后不会自动继承。
示例:
executor.submit(RunnableWrapper.of(() -> {
log.info("async task traceId={}", TraceContext.traceId());
doSomething();
}));如果项目有统一线程池封装,最好在任务提交处统一包装,不要让每个业务方法自己处理。
采样怎么做
Trace 很有价值,但全量保存会吃存储。采样要分两层看:
- Agent 侧采样:减少客户端采集和上报量。
- OAP 服务端采样:指标仍然聚合,但不保存所有 Trace 明细。
Agent 侧常见配置:
export SW_AGENT_SAMPLE=100
export SW_AGENT_SPAN_LIMIT=300SW_AGENT_SAMPLE=100 表示每 3 秒最多采样 100 个 TraceSegment。SW_AGENT_SPAN_LIMIT=300 限制单个 Segment 的 Span 数量,防止一个请求生成过多 Span。
OAP 服务端采样配置方向通常在 trace-sampling-policy-settings.yml:
default:
rate: 10000
duration: -1
services:
- name: mall-order
rate: 1000
duration: 3000这里的 rate 精度是万分之一,10000 表示 100%。duration 可以让慢 Trace 被保留下来,单位是毫秒。生产上常见做法是:普通请求降低采样,错误 Trace 和慢 Trace 尽量保留。
采样后的现象要提前告诉团队:
- UI 查不到某一条 Trace,不代表请求没发生,可能只是明细没保存。
- 服务、实例、端点、拓扑等指标仍然可以用于趋势判断。
- 故障期间可以临时提高采样,但要同时看 OAP 和存储压力。
- 如果大量请求都失败或变慢,错误/慢 Trace 保留策略可能把采样率顶得很高,要防止存储被打爆。
告警配置
SkyWalking 告警一般由规则和通知通道组成。规则看响应时间、成功率、实例延迟、端点延迟等指标;通知可以接 Webhook,再转企业微信、钉钉、短信、邮件或内部告警平台。
告警配置文件通常在:
config/alarm-settings.yml规则示例:
rules:
service_resp_time_rule:
metrics-name: service_resp_time
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: "Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes"Webhook 示例:
webhooks:
- http://alert-gateway.example.com/skywalking/alarm接收端至少要做到:
- 打印原始告警消息,方便调试规则。
- 去重和收敛,避免同一故障刷屏。
- 附带服务名、端点、时间窗口、规则名。
- 给出 UI 查询入口或排障手册链接。
测试时可以临时加一个慢接口:
@GetMapping("/slow")
public String slow() throws InterruptedException {
Thread.sleep(2000);
return "ok";
}压几次:
for i in {1..20}; do curl -s http://gateway.example.com/api/slow; done验证结果:
- UI 告警页面出现记录。
- Webhook 接收端收到 JSON。
- 告警平台能按服务和规则聚合。
- 恢复后告警不再持续触发。
生产部署建议
生产至少两个 OAP 节点:
Agent
-> oap-lb.example.com:11800
-> oap-01:11800
-> oap-02:11800也可以让 Agent 直接配置多个 OAP:
-Dskywalking.collector.backend_service=oap-01:11800,oap-02:11800UI 也要连多个 OAP 或统一入口,配置名称以当前 webapp.yml 或容器环境变量为准:
collector:
ribbon:
listOfServers: oap-01:12800,oap-02:12800把生产拓扑补全以后,SkyWalking 的边界会清楚很多:Agent 只负责采集和上报,OAP 负责接收、分析和查询,存储负责保留数据,UI 只是入口。真正会导致数据丢失或查询断档的,通常是 OAP 到存储这条链路、TTL 配置、备份恢复和磁盘容量。
上线评审时至少问四个问题:Agent 指向的 OAP 地址是否可滚动切换;UI 查的是哪个 OAP 查询入口;Trace 明细、指标、日志关联分别保留多久;存储快照恢复后能不能在临时环境查到同一时间段的 Trace 和拓扑。UI 挂了通常只是看不到页面,存储写入失败或 TTL 配错才会让历史数据真正丢失。
OAP 资源和三件事强相关:
- 服务数量。
- QPS 和 Trace 采样率。
- Span 数量和日志上报量。
上线前至少压这些场景:
业务正常流量
业务峰值流量
下游超时或错误率升高的故障流量
临时提高采样后的流量观察 OAP:
top -p $(pgrep -f skywalking-oap)
jstat -gcutil <oap_pid> 5s
ss -s
df -hOAP JVM 参数要按机器资源配置,不要默认无限吃内存:
export JAVA_OPTS="-Xms4g -Xmx4g -XX:+UseG1GC"安全边界也要提前定:
11800只允许业务网段访问。12800只允许 UI、运维网段或内网网关访问。- UI 不直接暴露公网。
- OAP 和存储之间走内网。
- 需要认证和 TLS 时,按官方文档配置 Agent token、TLS 或网关层认证。
- 告警 Webhook 必须鉴权。
防火墙检查:
firewall-cmd --list-ports
firewall-cmd --add-port=11800/tcp --permanent
firewall-cmd --add-port=12800/tcp --permanent
firewall-cmd --reload云服务器还要检查安全组。很多端口问题不是 Linux 防火墙,而是云安全组没放通。
常见故障排查
Agent 不生效
现象:
UI 没有服务
应用日志没有 SkyWalking Agent 启动信息
ps 看不到 -javaagent先查进程:
ps -ef | grep java | grep skywalking-agent
jps -lv | grep mall-user再查文件:
ls -l /opt/skywalking-agent/skywalking-agent.jar
ls -ld /opt/skywalking-agent /opt/skywalking-agent/logs再查日志:
grep -i "skywalking" /data/logs/mall-user/*.log
tail -n 200 /opt/skywalking-agent/logs/*.log常见原因:
-javaagent放在-jar后面。- Agent jar 路径不存在或权限不可读。
- 容器里没有挂载 Agent。
- 启动脚本覆盖了
JAVA_TOOL_OPTIONS。 - 使用了不兼容的 JDK、框架或插件版本。
修复后验证:
systemctl restart mall-user
ps -ef | grep mall-user | grep javaagent
curl http://gateway.example.com/api/users/1服务不上报
现象:
应用带了 -javaagent
UI 仍然没有服务
OAP 没有收到数据先查端口:
nc -vz oap.example.com 11800
ss -lntp | grep 11800再查启动参数:
ps -ef | grep mall-user | tr ' ' '\n' | egrep 'skywalking|SW_AGENT|backend|service'
env | egrep 'SW_AGENT|SKYWALKING'再查 OAP:
docker logs skywalking-oap --tail=200
tail -n 200 /opt/skywalking/logs/skywalking-oap-server.log常见原因:
- Agent 指向了
127.0.0.1:11800,但 OAP 不在本机。 - 容器网络里写了宿主机地址,但容器访问不到。
- 防火墙或安全组没放通
11800。 - OAP 启动失败或存储连接失败。
- UI 时间范围选错,或者根本没有真实请求。
链路断裂
现象:
Trace 只到 mall-user
mall-order 有日志,但 UI 没有下游 Span
拓扑图缺一段服务关系排查:
ps -ef | grep mall-order | grep javaagent
grep "TRACE_ID_FROM_UPSTREAM" /data/logs/mall-order/app.log
grep -i "plugin" /opt/skywalking-agent/logs/*.log处理顺序:
- 确认所有服务都接 Agent。
- 确认服务名没有配错。
- 校准 Gateway、Feign、MQ 插件和框架版本。
- 跨线程任务用 toolkit 包装。
- 临时提高采样复测。
Gateway 不显示
现象:
请求明明经过 Gateway
Trace 入口却从 mall-user 开始
拓扑图没有 mall-gateway排查:
ps -ef | grep mall-gateway | grep javaagent
ls /opt/skywalking-agent/plugins | grep -i gateway
ls /opt/skywalking-agent/optional-plugins | grep -i gateway处理:
- 确认 Gateway 服务接了 Agent。
- 校准 Spring Cloud Gateway 版本和 Agent 插件支持。
- 如果当前版本要求可选插件,把对应插件从
optional-plugins放到plugins。 - 重启 Gateway。
- 重新发请求,查最近 15 分钟 Trace。
日志 traceId 是 N/A
现象:
日志里出现 [TID: N/A]
或者 [%X{tid}] 为空排查:
grep -n "TraceIdPatternLogbackLayout" config/logback-spring.xml
grep -n "%tid\\|%X{tid}" config/logback-spring.xml
ps -ef | grep javaagent再打一次真实请求:
curl http://gateway.example.com/api/users/1
grep "api/users" /data/logs/mall-user/app.log如果接口日志里还是 N/A,重点查 Agent 是否生效、日志 layout 是否生效、当前日志是否在请求线程中、异步线程是否做了上下文传递。
时间不准
现象:
应用刚请求,UI 最近 15 分钟查不到
Trace 时间和日志时间差 8 小时
不同服务 Span 顺序看起来异常排查:
date
timedatectl
chronyc tracking
docker exec mall-user date
docker exec skywalking-oap date处理:
- 所有节点统一 NTP。
- 容器设置正确时区,或统一使用 UTC。
- 检查浏览器本地时间。
- UI 查询范围先放大到最近 1 小时复查。
链路追踪强依赖时间。生产环境如果 NTP 漂移,Trace 排序、耗时判断、告警窗口都会变得不可信。
端口不通
按链路查:
# 应用机器到 OAP gRPC
nc -vz oap.example.com 11800
# UI 机器到 OAP REST
nc -vz oap.example.com 12800
# 浏览器访问 UI
curl -I http://skywalking-ui.example.com/
# OAP 本机监听
ss -lntp | egrep '11800|12800'容器网络再查:
docker network ls
docker inspect skywalking-oap | grep -i network -A 20
docker exec mall-user nc -vz skywalking-oap 11800常见原因:
- Linux 防火墙没开。
- 云安全组没开。
- Compose 不在同一网络。
- Agent 配了宿主机
127.0.0.1。 - OAP 绑定了特定 IP,客户端却用另一个 IP 访问。
UI 有服务但 Trace 查不到
可能原因:
- 查询时间范围不对。
- 端点筛选条件太窄。
- 采样没保存这条 Trace。
- 存储写入失败。
- Trace 明细 TTL 已清理。
排查:
tail -n 200 /opt/skywalking/logs/skywalking-oap-server.log
curl -s http://elasticsearch:9200/_cat/indices/skywalking*?v处理:
- 放宽时间范围和筛选条件。
- 临时提高采样复测。
- 查 OAP 写存储错误。
- 查存储容量和索引状态。
存储增长过快
现象:
ES 磁盘快速增长
BanyanDB/ES 写入延迟升高
OAP 日志出现写入超时
UI 查询变慢先看容量:
curl -s http://elasticsearch:9200/_cat/indices/skywalking*?v&s=store.size:desc
curl -s http://elasticsearch:9200/_cat/nodes?v
df -h处理顺序:
- 降低 Trace 明细采样。
- 减少日志上报量,日志主体交给日志系统。
- 调短 Trace 明细 TTL。
- 检查是否给大量普通方法加了
@Trace。 - 检查高 QPS 接口 Span 数量。
- 扩容存储或拆分集群。
落地工程深水区
SkyWalking 上生产后,最容易出问题的是“看得到一条 Trace”,却没有把成本、边界和治理一起落地:
- 采样率要按接口价值分层。核心链路、慢请求和错误请求要尽量留证;普通高 QPS 查询接口可以降低采样。不要为了省磁盘把问题现场全部采没。
- TTL 和存储容量要一起治理。链路明细、指标、拓扑和日志关联的保留价值不同,不能用同一套周期粗暴处理。BanyanDB、Elasticsearch 的磁盘、水位和索引/分片策略要纳入监控。
- Agent 升级要灰度。Java Agent 会进入应用进程,和 JDK、字节码增强、类加载器、网关、RPC、异步线程都有关系,不能全量一把推。
- 服务名和实例名要稳定。随版本号、Pod 名、随机后缀变化的服务名会污染拓扑,也会让历史数据无法对齐。
- 日志关联要走 traceId,而不是把日志正文塞进链路系统。日志主体交给日志平台,SkyWalking 负责把请求链路和日志证据串起来。
- OAP 和存储要有高可用边界。OAP 可以多实例,存储要单独做备份、扩容和恢复演练;UI 挂了不等于链路数据丢了,存储挂了才是真事故。
- 告警要防噪声。慢接口、异常率、实例离线、OAP 堆积、存储写入失败都可以告警,但要和 Prometheus、日志平台的告警去重,避免同一事故刷三套系统。
- 安全边界不能省。OAP 接收端、UI、存储后端和告警 Webhook 不要裸露公网;跨环境接入要用独立地址、Token 或网关隔离。
- 回滚方案要简单。应用侧最直接的回滚是移除
-javaagent或切回旧 Agent;服务端升级前要备份配置、规则和存储数据,保留旧镜像或旧安装包。
上线检查清单
发布前逐项确认:
- OAP、UI、存储版本和 Java Agent 版本已确认。
- Agent 支持当前 JDK 和框架版本。
11800、12800、UI 端口放通范围正确。- 服务名规范,不和历史服务混淆。
- 存储不是 H2 或临时目录。
- 采样率、Span 限制、TTL 已配置。
- 日志里能打印 traceId。
- 告警 Webhook 可达且有去重。
- 离线包、镜像、Maven 依赖已入库。
- 回滚方案明确:移除
-javaagent或切回旧 Agent。
上线后马上验证:
- 访问核心接口,UI 能看到服务、端点、Trace。
- 拓扑关系符合真实调用。
- 慢接口 Trace 能定位到具体 Span。
- 日志按 traceId 能搜到多服务记录。
- OAP CPU、内存、GC 正常。
- 存储写入正常,磁盘增长符合预期。
- 告警规则不会误报刷屏。
故障时按这个顺序来:
- 先确认 UI 时间范围。
- 找服务、端点、失败 Trace。
- 打开瀑布图看最慢或错误 Span。
- 用 traceId 查日志。
- 判断是当前服务、下游服务、网络、数据库还是链路断裂。
- 修复后用同一请求路径复测。
常用命令速查
# 查看 OAP/UI 端口
ss -lntp | egrep '11800|12800|8080'
# 应用机器验证 OAP gRPC 端口
nc -vz oap.example.com 11800
# UI 机器验证 OAP REST 端口
nc -vz oap.example.com 12800
# 查看 Java 进程是否带 Agent
ps -ef | grep java | grep skywalking-agent
jps -lv | grep -i skywalking
# 查看应用启动参数
ps -ef | grep mall-user | tr ' ' '\n' | egrep 'javaagent|skywalking|SW_AGENT'
# 查看 Agent 日志
tail -n 200 /opt/skywalking-agent/logs/*.log
# 查看 OAP 日志
tail -f /opt/skywalking/logs/skywalking-oap-server.log
docker logs -f skywalking-oap
# 查看 UI 日志
tail -f /opt/skywalking/logs/webapp.log
docker logs -f skywalking-ui
# 查看 ES 状态
curl -s http://elasticsearch:9200/_cluster/health?pretty
curl -s http://elasticsearch:9200/_cat/indices/skywalking*?v
# 按 traceId 查日志
grep "TRACE_ID" /data/logs/*/*.log配置模板
普通 jar 启动脚本:
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="mall-user"
APP_JAR="/data/apps/${APP_NAME}/${APP_NAME}.jar"
AGENT_JAR="/opt/skywalking-agent/skywalking-agent.jar"
OAP_ADDR="oap-01.example.com:11800,oap-02.example.com:11800"
exec java \
-javaagent:${AGENT_JAR} \
-Dskywalking.agent.service_name=${APP_NAME} \
-Dskywalking.collector.backend_service=${OAP_ADDR} \
-Xms1g -Xmx1g \
-jar "${APP_JAR}"Docker Compose 业务服务:
services:
mall-user:
image: harbor.example.com/mall/mall-user:1.0.0
environment:
JAVA_TOOL_OPTIONS: "-javaagent:/opt/skywalking-agent/skywalking-agent.jar"
SW_AGENT_NAME: "mall-user"
SW_AGENT_COLLECTOR_BACKEND_SERVICES: "oap-01.example.com:11800,oap-02.example.com:11800"
TZ: "Asia/Shanghai"
volumes:
- /opt/skywalking-agent:/opt/skywalking-agent:ro
- /data/logs/mall-user:/data/logs/mall-user
restart: unless-stoppedlogback 文件输出:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/data/logs/mall-user/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>/data/logs/mall-user/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>200MB</maxFileSize>
<maxHistory>14</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<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="FILE"/>
</root>
</configuration>官方文档入口
- Apache SkyWalking Downloads: https://skywalking.apache.org/downloads/
- SkyWalking Backend Docker: https://skywalking.apache.org/docs/main/latest/en/setup/backend/backend-docker/
- SkyWalking OAP IP and port: https://skywalking.apache.org/docs/main/latest/en/setup/backend/backend-ip-port/
- SkyWalking Backend Storage: https://skywalking.apache.org/docs/main/latest/en/setup/backend/backend-storage/
- SkyWalking TTL: https://skywalking.apache.org/docs/main/latest/en/setup/backend/ttl/
- SkyWalking Trace Sampling: https://skywalking.apache.org/docs/main/latest/en/setup/backend/trace-sampling/
- SkyWalking Java Agent Setup: https://skywalking.apache.org/docs/skywalking-java/latest/en/setup/service-agent/java-agent/readme/
- SkyWalking Java Agent Configuration: https://skywalking.apache.org/docs/skywalking-java/latest/en/setup/service-agent/java-agent/configurations/
- SkyWalking Logback Toolkit: https://skywalking.apache.org/docs/skywalking-java/latest/en/setup/service-agent/java-agent/application-toolkit-logback-1.x/
- SkyWalking Spring Gateway Plugin: https://skywalking.apache.org/docs/skywalking-java/latest/en/setup/service-agent/java-agent/agent-optional-plugins/spring-gateway/
