下一篇【第74篇】SkyWalking 9.x新特性——K8s原生集成、Continuous Profiling与Layer概念
上一篇【第76篇】SkyWalking完整技术栈选型决策树——从Agent到OAP到存储的企业级选型指南


一、开篇 —— 每个SkyWalking用户的必修课

在SkyWalking社区,有一个流传很久的笑话:

“安装SkyWalking只需要5分钟,排查SkyWalking为什么没数据需要5小时。”

这不是玩笑。SkyWalking作为一个分布式系统,涉及Agent、网络、OAP、存储四个环节,任何一个环节出问题,都会导致"看起来一切正常,但就是没数据"。

本文是我在生产环境中"填坑"多年的经验总结,用最直白的话讲最实战的排查思路。每一个坑背后都有一个深夜排查的血泪故事。

二、第一大坑:Agent不上报数据

这是最高频的问题,没有之一。

2.1 从外到内的六步排查法

+------------------------------------------------------------------+
|          Agent不上报数据的六步排查法                                |
+------------------------------------------------------------------+
|                                                                    |
|  Step 1: Agent启动了吗?                                           |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 检查: 启动日志中有没有SkyWalking的日志             │           │
|  │ 命令: grep "SkyWalking" app.log                    │           │
|  │ 正常: "SkyWalking Agent 9.7.0 initialized"        │           │
|  │ 异常: 没有 → 检查 -javaagent: 参数是否正确配置     │           │
|  └────────────────────────────────────────────────────┘           │
|                              │                                     │
|                    没有日志?  ↓                                     │
|                              │                                     │
|  Step 2: Agent加载了你的插件吗?                                    |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 检查: plugins/ 目录下的Jar是否正确                  │           │
|  │ 注意: 有些Jar需要放 optional-plugins/              │           │
|  │       有些Jar需要放 bootstrap-plugins/              │           │
|  │ 命令: ls skywalking-agent/plugins/                  │           │
|  └────────────────────────────────────────────────────┘           │
|                              │                                     │
|                    插件没问题? ↓                                    │
|                              │                                     │
|  Step 3: 网络通吗?                                                |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 检查: Agent能否连接到OAP                            │           │
|  │ 命令: telnet oap-server 11800                      │           │
|  │ 正常: Connected to oap-server                      │           │
|  │ 异常: Connection refused / timeout                 │           │
|  │ → 检查防火墙/安全组/网络策略                       │           │
|  └────────────────────────────────────────────────────┘           │
|                              │                                     │
|                    网络通的?  ↓                                     │
|                              │                                     │
|  Step 4: 注册成功了吗?                                            |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 检查: OAP日志中是否有注册记录                       │           │
|  │ 命令: grep "register" oap.log                      │           │
|  │ 正常: "register service [order-service] success"  │           │
|  │ 异常: 没有注册日志 → 检查service_name配置          │           │
|  │       agent.service_name=${SW_AGENT_NAME:YourName} │           │
|  └────────────────────────────────────────────────────┘           │
|                              │                                     │
|                    注册成功?  ↓                                     │
|                              │                                     │
|  Step 5: 数据真的发了吗?                                          |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 检查: Agent的GRPCChannel状态                        │           │
|  │ 日志: "Report trace segment to collector"          │           │
|  │ 如果没有 → Trace没有被创建 → 检查插件是否拦截      │           │
|  └────────────────────────────────────────────────────┘           │
|                              │                                     │
|                    数据发了?  ↓                                     │
|                              │                                     │
|  Step 6: OAP处理了吗?                                             |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 检查: OAP日志中是否有数据处理记录                   │           │
|  │ 检查: ES中是否有新数据                              │           │
|  │ curl "localhost:9200/segment*/_count"               │           │
|  │ → 如果ES有数据但UI看不到 → 可能是时间范围问题       │           │
|  └────────────────────────────────────────────────────┘           │
|                                                                    |
+------------------------------------------------------------------+

2.2 一个经典案例

案例:Agent启动正常、网络通、注册成功,但UI上就是没数据。

排查过程

# 1. Agent日志里搜索"report"
grep "report" agent.log
# 结果: (空) → Trace根本没产生!

# 2. 检查应用代码
# 发现:应用是一个纯定时任务,没有任何HTTP请求或RPC调用
# 定时任务里直接操作数据库 → 没有创建EntrySpan!

# 3. 解决方案
# 为定时任务添加手动追踪
@Scheduled(fixedDelay = 60000)
public void myTask() {
    AbstractSpan span = ContextManager.createEntrySpan(
        "/scheduled/myTask", null
    );
    try {
        // 定时任务逻辑
    } finally {
        ContextManager.stopSpan();
    }
}

教训:纯批处理/定时任务应用需要手动创建EntrySpan,因为SkyWalking不会自动拦截main方法或@ Scheduled方法。

三、第二大坑:Trace数据不完整

3.1 截断的Trace是运营的噩梦

+------------------------------------------------------------------+
+          Trace不完整的几种典型症状                                   +
+------------------------------------------------------------------+
|                                                                    |
|  症状1: "只有入站,没有出站"                                        |
|  ┌────────────────────────────────────────────────────┐           │
|  │ Agent A (order-service)        Agent B (user-svc)  │           │
|  │ ┌─────────┐                   ┌─────────┐         │           │
|  │ │EntrySpan│ ── OKHttp调用 ──→ │ ???     │         │           │
|  │ │         │                   │ 没数据! │         │           │
|  │ └─────────┘                   └─────────┘         │           │
|  │                                                    │           │
|  │ 原因: Agent B的插件没拦截到请求                     │           │
|  │ → 检查user-svc的skywalking-agent配置               │           │
|  │ → OKHttp插件是否启用: plugin.okhttp.trace = true   │           │
|  └────────────────────────────────────────────────────┘           │
|                                                                    |
|  症状2: "方法调用丢失"                                             |
|  ┌────────────────────────────────────────────────────┐           │
|  │ Trace中看到:                                         │           │
|  │ EntrySpan → ExitSpan(DB)                           │           │
|  │ 但中间应该还有一个LocalSpan(缓存查询)不见了!         │           │
|  │                                                    │           │
|  │ 原因: 缓存客户端(Redis/Caffeine)插件未加载          │           │
|  │ → 检查对应插件Jar是否在plugins/目录下               │           │
|  └────────────────────────────────────────────────────┘           │
|                                                                    |
|  症状3: "Span有但没有父子关系"                                     |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 两个Span显示为独立的Trace,而非父子关系              │           │
|  │                                                    │           │
|  │ 原因: sw8 header丢失                               │           │
|  │ → 检查HTTP Client是否过滤了Header                  │           │
|  │ → 检查Nginx/网关是否透传自定义Header               │           │
|  │ → 检查Dubbo Filter是否有自定义逻辑                 │           │
|  └────────────────────────────────────────────────────┘           │
|                                                                    |
+------------------------------------------------------------------+

3.2 Trace不完整排查清单

# Trace完整性排查

# 1. 检查sw8 header是否被传播
# 在服务端打印所有Header
@GetMapping("/test")
public String test(HttpServletRequest request) {
    Enumeration<String> headers = request.getHeaderNames();
    while (headers.hasMoreElements()) {
        String name = headers.nextElement();
        System.out.println(name + ": " + request.getHeader(name));
    }
    return "ok";
}

# 如果sw8 header缺失:
# - 检查网关/LoadBalancer是否过滤了自定义Header
# - Nginx: proxy_pass_request_headers on;
# - Spring Cloud Gateway: 检查Filter顺序

# 2. 检查异步调用
# @Async方法中的Trace是否连续
# → 确保使用了ContextSnapshot

四、第三大坑:告警不触发

4.1 告警规则的调试

# 告警调试配置
rules:
  # 调试用的小阈值规则
  test_alert:
    metrics-name: service_cpm
    threshold: 1  # 只要有一次调用就告警
    op: ">"
    period: 1     # 只检查1分钟
    count: 1      # 出现1次就告警
    message: "TEST: service {name} has traffic"
    
# 如果这个告警都不触发,说明:
# 1. OAP没收到Metrics数据
# 2. 告警规则格式有问题
# 3. 告警配置没有被OAP加载

4.2 告警不触发的常见原因

原因1: 告警规则文件位置不对
- 检查: oap-server/config/alarm-settings.yml 是否存在
- 如果通过ConfigMap挂载,确认挂载路径正确

原因2: 指标名拼写错误
- service_resp_time ✓
- service_response_time ✗

原因3: OAP没有重启加载新规则
- 需要重启OAP或使用动态配置

原因4: 告警通知渠道配置错误
- 检查webhook URL是否可达
- 检查钉钉/企业微信的token是否正确

原因5: 静默期未过
- silence-period: 10 → 告警后10分钟内不再发送
- 调整silence-period或等静默期过去

五、第四大坑:Elasticsearch存储问题

5.1 ES集群变红

# 症状:SkyWalking UI打开很慢或报错

# 排查:
# 1. 检查ES集群健康
curl http://es-node:9200/_cluster/health
# {"status":"red",...} ← 危险!

# 2. 检查磁盘
curl http://es-node:9200/_cat/allocation?v
# 如果磁盘使用率 > 85% → ES会拒绝写入

# 3. 紧急处理
# 删除旧索引释放空间
curl -X DELETE "http://es-node:9200/sw_segment-20260701"
# 或调高磁盘水位线(临时方案)
curl -X PUT "http://es-node:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
  "transient": {
    "cluster.routing.allocation.disk.watermark.low": "90%",
    "cluster.routing.allocation.disk.watermark.high": "95%"
  }
}'

5.2 索引爆炸

# 问题: 每天产生几百个索引,ES性能急剧下降

# 原因分析:
# SkyWalking为每种指标类型创建按天分片的索引
# 如果指标类型很多(自定义了很多OAL指标),索引数量会爆炸

# 解决方案:
# 1. 限制索引保留天数
storage:
  elasticsearch:
    traceDataTTL: 7   # Trace保留7天
    metricDataTTL: 7  # 指标保留7天
    recordDataTTL: 7  # 记录保留7天

# 2. 定时清理旧索引
# 创建ES ILM策略(Index Lifecycle Management)
# 或者使用CronJob定时删除
0 2 * * * curl -X DELETE "http://es:9200/sw_*-$(date -d '8 days ago' +%Y%m%d)"

六、第五大坑:UI展示异常

# 症状1: 拓扑图显示白屏
# 排查:
# 1. 浏览器F12 → Console → 看JS报错
# 2. 检查OAP的GraphQL接口是否正常
curl http://oap-server:12800/graphql
# 3. 清除浏览器缓存
# 4. 升级UI版本(可能和OAP版本不匹配)

# 症状2: Trace详情页加载超时
# 排查:
# 1. 检查ES查询速度
# 2. 检查网络(UI→OAP→ES)
# 3. Trace数据量太大(超过ES默认限制)
# 设置 OAP 参数
# SW_CORE_GRPC_MAX_MESSAGE_SIZE=104857600

# 症状3: Dashboard加载不出来
# 排查:
# 检查GraphQL查询是否正确
# 有可能是OAP版本和UI版本不一致
# 查看UI容器的日志: kubectl logs deployment/skywalking-ui

七、第六大坑:升级SkyWalking版本

7.1 升级惨案与正确姿势

+------------------------------------------------------------------+
|          升级SkyWalking的正确姿势                                    |
+------------------------------------------------------------------+
|                                                                    |
|  ❌ 错误做法:                                                       |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 1. 周五下午直接升                                    │           │
|  │ 2. 不备份就升                                        │           │
|  │ 3. 跨多个大版本升                                    │           │
|  │ 4. 全量切换,不留灰度                                │           │
|  └────────────────────────────────────────────────────┘           │
|                                                                    |
|  ✓ 正确做法:                                                       |
|  ┌────────────────────────────────────────────────────┐           │
|  │ 1. 周二/周三升级(留足修复时间)                     │           │
|  │ 2. 先搭验证环境,用生产数据量压测                   │           │
|  │ 3. 确认Agent和OAP版本兼容                          │           │
|  │ 4. 逐步灰度:先升20% Agent → 观察 → 全部升Agent   │           │
|  │ 5. 升OAP:先启一个新版本OAP集群 → 切换流量 → 停旧  │           │
|  │ 6. 保留旧版本环境一周(快速回退能力)               │           │
|  └────────────────────────────────────────────────────┘           │
|                                                                    |
+------------------------------------------------------------------+
# 升级检查清单
# ==============
# 1.0 升级前
echo "=== 升级前检查 ==="
echo "1. 确认当前版本:"
grep "version" skywalking-agent/config/agent.config
echo "2. 确认目标版本Release Notes"
echo "3. 备份OAP配置和ES数据"
echo "4. 确认新版本Agent兼容旧版本OAP(滚动升级的关键)"

# 2.0 升级步骤
echo "=== Agent灰度升级 ==="
# 先升级1个Pod的Agent,观察15分钟
kubectl set image deployment/order-service \
  app=order-service:v2-with-new-agent

# 检查:
# - UI上是否有新数据
# - 告警是否正常
# - Agent日志有没有异常

# 3.0 OAP升级
echo "=== OAP升级 ==="
# 使用新namespace部署新版本OAP
helm install skywalking-v2 skywalking/skywalking \
  --namespace monitoring-v2 \
  --values new-values.yaml \
  --set oap.image.tag=9.3.0

# 将Agent流量逐步切到新OAP
# 观察数据完整性
# 确认无误后,停止旧OAP

八、总结:防坑口诀

+------------------------------------------------------------------+
|           SkyWalking生产防坑口诀                                    |
+------------------------------------------------------------------+
|                                                                    |
|  Agent不上报 → 六步排查 (启动→插件→网络→注册→发送→处理)            |
|  Trace断了 → 找sw8 header (网关/代理/Filter 没透传?)               |
|  告警不触发 → 调试规则 (先验证最简单的告警能否触发)                 |
|  ES红了 → 马上看磁盘 + 删旧索引                                    |
|  UI白屏 → F12看Console + 清缓存                                    |
|  要升级 → 选周二 + 先灰度Agent + 再升OAP                           |
|                                                                    |
+------------------------------------------------------------------+

下一篇【第74篇】SkyWalking 9.x新特性——K8s原生集成、Continuous Profiling与Layer概念
上一篇【第76篇】SkyWalking完整技术栈选型决策树——从Agent到OAP到存储的企业级选型指南


Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐