
上一篇【第21篇】用SkyWalking排查慢服务——从蛛丝马迹到真相大白下一篇【第23篇】SkyWalking与单体应用——老系统也能焕发新活力1. 引言告警是系统的痛觉神经想象一下你正在海边度假脚踩沙滩手捧椰子突然手机收到一条短信“订单服务P99响应时间超过5秒请速处理”——你打开运维群发现大家已经根据告警信息定位到了问题正在热火朝天地修复。你想登录VPN帮忙同事回复“不用正在切流量你继续度假。”这才是现代运维的理想状态不是人找问题而是问题找人。SkyWalking的告警系统就是系统的痛觉神经——哪里出了问题它能第一时间感知并通知你。上篇文章我们学会了排查慢服务这篇文章我们聊聊如何让系统学会主动喊救命。2. 告警系统的整体架构------------------------------------------------------------------ | SkyWalking 告警系统架构 | ------------------------------------------------------------------ | | | ① 指标采集层 | | ┌──────────────────────────────────────────┐ | | │ Agent → OAP Receiver → Metrics Aggregation│ | | │ (每秒采集 → 分钟聚合 → 持久化到存储) │ | | └──────────────────┬───────────────────────┘ | | │ | | ▼ | | ② 告警引擎层 | | ┌──────────────────────────────────────────┐ | | │ Alarm Core 每10秒轮询一次指标 │ | | │ ┌────────────────────────────────────┐ │ | | │ │ 匹配告警规则 → 检查触发条件 │ │ | | │ │ → 累加触发次数 → 满足阈值则告警 │ │ | | │ └────────────────────────────────────┘ │ | | └──────────────────┬───────────────────────┘ | | │ | | ▼ | | ③ 通知分发层 | | ┌──────────────────────────────────────────┐ | | │ Webhook | DingTalk | WeChat | Slack | ... │ | | └──────────────────────────────────────────┘ | | │ | | ▼ | | ④ 用户接收 | | ┌──────────────────────────────────────────┐ | | │ 运维人员 → 收到通知 → 查阅SkyWalking UI │ | | │ → 定位问题 → 修复确认 │ | | └──────────────────────────────────────────┘ | ------------------------------------------------------------------3. alarm-settings.yml 配置详解3.1 文件位置与加载方式告警配置文件通常位于OAP Server的config/alarm-settings.yml。在Kubernetes环境中这通常通过ConfigMap挂载# k8s configmap 示例apiVersion:v1kind:ConfigMapmetadata:name:skywalking-oap-alarm-confignamespace:monitoringdata:alarm-settings.yml:|rules: # 告警规则定义在这里 webhooks: # 通知渠道配置 # ... 其余配置3.2 告警规则的基本语法一条告警规则由7个核心字段组成rules:# 规则名称唯一标识service_resp_time_rule:# 指标名称来自OAL脚本的定义metrics-name:service_resp_time# 比较操作符 op:# 阈值threshold:1000# 统计周期分钟表示计算最近N分钟的数据period:10# 触发次数在period内满足条件count次才真正告警count:3# 静默期分钟告警后N分钟内不再重复发送silence-period:5# 告警消息模板message:服务{name}的响应时间超过 1000ms当前值:{value}ms这7个字段构成了告警规则的DNA------------------------------------------------------------------ | 告警规则字段关系图 | ------------------------------------------------------------------ | | | metrics-name ──→ 从OAL定义的指标池中选取 | | | | | ▼ | | op threshold ──→ 定义什么是异常 | | | | | ▼ | | period count ──→ 定义有多异常才算告警 | | | (period内count次超过阈值才触发) | | ▼ | | silence-period ──→ 定义告警后多久别再烦我 | | | | | ▼ | | message ──→ 定义告警时告诉我什么 | ------------------------------------------------------------------这里有一个新手常踩的坑period和count的组合决定了告警灵敏度。比如period10, count3表示过去10分钟内有3次每10秒一次轮询超过阈值就告警。如果设为period3, count1告警会非常灵敏但也容易产生噪音。4. 内置告警指标详解4.1 服务级别指标# 服务平均响应时间service_resp_time:metrics-name:service_resp_timeop:threshold:1000period:10count:3silence-period:5message:服务{name}平均响应时间超过1秒# 服务成功率低于阈值告警service_sla:metrics-name:service_slaop:threshold:95# 成功率低于95%告警period:10count:2silence-period:5message:服务{name}成功率低于95%当前值:{value}%# 服务CPM每分钟调用量service_cpm:metrics-name:service_cpmop:threshold:10000period:10count:2silence-period:10message:服务{name}每分钟调用量超过100004.2 端点级别指标# 端点平均响应时间endpoint_avg_rule:metrics-name:endpoint_avgop:threshold:2000period:10count:2silence-period:5message:端点{name}平均响应时间超过2s# 端点成功率endpoint_sla_rule:metrics-name:endpoint_slaop:threshold:90period:10count:2silence-period:5message:端点{name}成功率低于90%4.3 数据库/实例级别指标# 数据库访问平均响应时间database_access_resp_time_rule:metrics-name:database_access_resp_timeop:threshold:100period:10count:3silence-period:5message:数据库访问平均响应时间超过100ms# 实例JVM内存告警instance_jvm_old_gc_time_rule:metrics-name:instance_jvm_young_gc_time# 或 old_gc_timeop:threshold:1000period:10count:1silence-period:5message:实例{name}JVM GC时间超过1s4.4 完整的内置指标速查表------------------------------------------------------------------ | 常用告警指标速查表 | ------------------------------------------------------------------ | 指标名称 | 含义 | 典型阈值 | ------------------------------------------------------------------ | service_resp_time | 服务平均RT | 1000ms | | service_sla | 服务成功率 | 99% | | service_cpm | 服务每分钟调用| 5000 | | service_apdex | 服务Apdex分 | 0.9 | | endpoint_avg | 端点平均RT | 2000ms | | endpoint_sla | 端点成功率 | 95% | | endpoint_cpm | 端点每分钟调用| 1000 | | database_access_resp_time | DB平均RT | 50ms | | database_access_sla | DB成功率 | 99% | | instance_jvm_old_gc_time | Old GC耗时 | 2000ms | | instance_jvm_young_gc_time | Young GC耗时 | 1000ms | | instance_jvm_young_gc_count | Young GC次数 | 10/min | | instance_cpu_percentage | CPU使用率 | 80% | | instance_jvm_memory_heap_usage | 堆内存使用率 | 85% | ------------------------------------------------------------------5. 自定义告警规则实战5.1 场景一慢端点聚合告警假设你的系统有200个端点不想每个端点超时都单独告警。可以创建一个全局慢端点数量告警# 先定义OAL脚本oal/core.oal// 统计过去10分钟平均响应时间2s的端点数 slow_endpoint_count from(Endpoint.latency) .filter(latency2000) .count();# alarm-settings.yml中引用slow_endpoint_count_rule:metrics-name:slow_endpoint_countop:threshold:10period:10count:1silence-period:10message:当前有{value}个端点的响应时间超过2秒请检查系统健康状态5.2 场景二错误率突增告警# OAL脚本endpoint_error_rate from(Endpoint.*).filter(status false) .count() .percentage();endpoint_error_burst_rule:metrics-name:endpoint_error_rateop:threshold:5# 错误率超过5%period:5count:2silence-period:5message:端点{name}错误率飙升至{value}%请立即检查5.3 场景三业务级别的自定义指标// 在业务代码中埋点importorg.apache.skywalking.apm.toolkit.meter.MeterFactory;importio.micrometer.core.instrument.Counter;ComponentpublicclassOrderMetrics{privatestaticfinalCounterORDER_FAIL_COUNTERMeterFactory.counter(order_fail_total).tag(type,payment).build();publicvoidrecordOrderFail(Stringreason){ORDER_FAIL_COUNTER.increment();}}然后通过Prometheus Fetcher将自定义指标导入SkyWalkingv9支持或使用OpenTelemetry桥接。6. 告警通知渠道配置6.1 Webhook通用回调# alarm-settings.ymlwebhooks:-http://your-webhook-service:8080/alarmWebhook的POST请求体格式如下[{scopeId:1,scope:SERVICE,name:order-service,id0:1,id1:0,ruleName:service_resp_time_rule,alarmMessage:服务 order-service 的响应时间超过 1000ms当前值: 2345ms,startTime:1617800000000}]自定义Webhook处理服务示例RestControllerRequestMapping(/alarm)publicclassAlarmWebhookController{PostMappingpublicResponseEntityStringhandleAlarm(RequestBodyListAlarmMessagealarms){for(AlarmMessagealarm:alarms){// 1. 记录到数据库alarmLogService.save(alarm);// 2. 按严重级别路由if(isCritical(alarm)){urgentNotifyService.send(alarm);// 电话/短信}else{normalNotifyService.send(alarm);// 群消息/邮件}// 3. 自动创建工单ticketService.createTicket(alarm);}returnResponseEntity.ok(received);}privatebooleanisCritical(AlarmMessagealarm){returnalarm.getAlarmMessage().contains(成功率)||alarm.getAlarmMessage().contains(错误率);}}6.2 钉钉DingTalk通知dingtalkHooks:# 钉钉群机器人Webhook URL-url:https://oapi.dingtalk.com/robot/send?access_tokenYOUR_TOKEN# 加签密钥安全设置secret:YOUR_SECRET钉钉机器人收到的消息格式【SkyWalking告警】 告警规则: service_resp_time_rule 告警服务: order-service 告警消息: 服务 order-service 的响应时间超过 1000ms当前值: 2345ms 告警时间: 2026-07-02 14:30:006.3 企业微信WeChat通知wechatHooks:-url:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?keyYOUR_KEY6.4 Slack通知slackHooks:-url:https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK6.5 通知渠道配置对比图------------------------------------------------------------------ | 告警通知渠道对比 | ------------------------------------------------------------------ | | | 渠道 | 配置复杂度 | 到达率 | 适用场景 | ------------------------------------------------------------------ | Webhook | ⭐⭐⭐ | 自定义 | 自定义告警处理流程 | | DingTalk | ⭐⭐ | ★★★★ | 国内企业团队首选 | | WeChat | ⭐⭐ | ★★★★★ | 微信办公场景 | | Slack | ⭐⭐ | ★★★★ | 国际化团队/国外企业 | | Feishu | ⭐⭐ | ★★★★ | 飞书用户 | ------------------------------------------------------------------7. 告警静默与分级7.1 静默期silence-periodsilence-period是告警系统的冷却时间:rules:service_resp_time_rule:silence-period:30# 告警后30分钟不再重复工作流程------------------------------------------------------------------ | 告警静默期工作原理 | ------------------------------------------------------------------ | | | 时间线: | | ──────────────────────────────────────────────────────────────→ | | | | 14:00 触发告警 ✅ 发送通知 | | 14:05 再次触发 静默中不发送 | | 14:15 再次触发 静默中不发送 | | 14:30 静默期结束 | | 14:35 再次触发 ✅ 发送通知新一轮告警开始 | | | ------------------------------------------------------------------7.2 告警分级策略在大型系统中告警需要分级处理。可以通过多个规则实现rules:# P3 - 低优先级响应时间超过1秒service_resp_time_p3:metrics-name:service_resp_timeop:threshold:1000period:10count:3silence-period:30message:[P3]服务{name}响应时间超过1秒# P2 - 中优先级响应时间超过3秒service_resp_time_p2:metrics-name:service_resp_timeop:threshold:3000period:5count:2silence-period:10message:[P2]服务{name}响应时间超过3秒需要关注# P1 - 高优先级成功率低于95%service_sla_p1:metrics-name:service_slaop:threshold:95period:3count:1silence-period:5message:[P1] 服务{name}成功率低于95%请立即处理# P0 - 紧急成功率低于80%service_sla_p0:metrics-name:service_slaop:threshold:80period:2count:1silence-period:3message:[P0] 服务{name}成功率暴跌至{value}%需要立即介入7.3 告警分级处理流程图------------------------------------------------------------------ | 告警分级处理流程 | ------------------------------------------------------------------ | | | 告警触发 | | │ | | ┌──────────┼──────────┐ | | ▼ ▼ ▼ | | P3 P2 P0/P1 | | 低优先级 中优先级 高优先级 | | │ │ │ | | ▼ ▼ ▼ | | ┌────────┐ ┌────────┐ ┌────────┐ | | │钉钉群 │ │钉钉群 │ │电话短信│ | | │普通消息│ │值班人 │ │钉钉all│ | | └────────┘ └────────┘ └────────┘ | | │ │ │ | | ▼ ▼ ▼ | | ┌────────┐ ┌────────┐ ┌────────┐ | | │自动记录│ │自动建 │ │自动建 │ | | │工单 │ │工单 │ │工单 │ | | │ │ │排期 │ │拉群 │ | | └────────┘ └────────┘ └────────┘ | ------------------------------------------------------------------8. 告警配置的生产级最佳实践8.1 告警抑制当某个上游服务挂了所有下游服务都会告警——这叫告警风暴。SkyWalking的告警目前原生不支持抑制但可以通过Webhook端实现// 告警抑制逻辑示例publicclassAlarmSuppressor{privateMapString,LongsuppressedServicesnewConcurrentHashMap();publicbooleanshouldSuppress(AlarmMessagealarm){// 如果上游服务已告警抑制下游StringserviceNamealarm.getName();StringupstreamgetUpstream(serviceName);if(suppressedServices.containsKey(upstream)){log.info(抑制告警: {} (因上游 {} 已告警),serviceName,upstream);returntrue;}returnfalse;}}8.2 告警通知的黄金法则宁可漏报不可滥报告警噪音是运维最大的敌人P0告警必须有人响应配置值班表和升级机制告警信息要有上下文不只是CPU高了而是order-service的CPU达到90%正值业务高峰期告警要有药方附带Runbook链接告诉运维该怎么处理定期复盘告警哪些告警是误报哪些阈值需要调整8.3 动态阈值 vs 静态阈值------------------------------------------------------------------ | 静态阈值 vs 动态阈值 | ------------------------------------------------------------------ | | | 静态阈值: | | 服务响应时间超过1秒就告警 | | ┌────────────────────────────────┐ | | │ 优点: 简单直接一目了然 │ | | │ 缺点: 不区分白天/夜间/高峰期 │ | | │ 低峰期1秒可能正常 │ | | └────────────────────────────────┘ | | | | 动态阈值: | | 服务响应时间超过历史均值的2倍就告警 | | ┌────────────────────────────────┐ | | │ 优点: 自适应减少误报 │ | | │ 缺点: 实现复杂需要历史数据 │ | | │ SkyWalking原生暂不支持 │ | | │ 可通过PrometheusAlertManager │ | | │ 结合实现动态阈值 │ | | └────────────────────────────────┘ | ------------------------------------------------------------------8.4 生产环境完整告警配置示例# alarm-settings.yml 生产级配置rules:# 服务级别 service_resp_time_rule:metrics-name:service_resp_timeop:threshold:1000period:10count:3silence-period:30message:[P3] 服务 {name} 平均响应时间 {value}msservice_sla_rule:metrics-name:service_slaop:threshold:95period:5count:2silence-period:10message:[P1] 服务 {name} 成功率降至 {value}%# 数据库 database_access_resp_time_rule:metrics-name:database_access_resp_timeop:threshold:100period:10count:3silence-period:10message:[P2] 数据库访问平均延迟 {value}ms# JVM instance_jvm_old_gc_time_rule:metrics-name:instance_jvm_old_gc_timeop:threshold:2000period:5count:1silence-period:10message:[P2] 实例 {name} Full GC时间 {value}msinstance_jvm_memory_heap_usage_rule:metrics-name:instance_jvm_memory_heap_usageop:threshold:85period:10count:2silence-period:10message:[P2] 实例 {name} 堆内存使用率 {value}%# 通知渠道 webhooks:-http://alarm-gateway.internal:8080/api/alarmdingtalkHooks:-url:https://oapi.dingtalk.com/robot/send?access_tokenxxxsecret:xxx9. 总结SkyWalking的告警系统像一位不知疲倦的哨兵指标选得好从服务、端点、数据库到JVM覆盖所有关键维度规则配得巧period count组合找到灵敏度与噪音的平衡通知发得准Webhook/钉钉/企微/Slack多通道分级通知静默设得稳silence-period防止告警风暴把告警想象成你手机的勿扰模式——重要电话P0/P1永远不静音普通通知P3按你的节奏来。下一篇文章我们将回到一个看似传统但非常重要的场景——SkyWalking在单体应用中的应用看看这个云原生时代的APM如何在老系统中发光发热。上一篇【第21篇】用SkyWalking排查慢服务——从蛛丝马迹到真相大白下一篇【第23篇】SkyWalking与单体应用——老系统也能焕发新活力