【SkyWalking从入门到精通】第22篇:SkyWalking告警配置实战——让你的系统学会“喊救命“
上一篇【第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的组合决定了告警灵敏度。比如period=10, count=3表示:过去10分钟内,有3次(每10秒一次轮询)超过阈值就告警。如果设为period=3, count=1,告警会非常灵敏,但也容易产生噪音。
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(latency>2000) .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_COUNTER=MeterFactory.counter("order_fail_total").tag("type","payment").build();publicvoidrecordOrderFail(Stringreason){ORDER_FAIL_COUNTER.increment();}}然后通过Prometheus Fetcher将自定义指标导入SkyWalking(v9+支持),或使用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处理服务示例:
@RestController@RequestMapping("/alarm")publicclassAlarmWebhookController{@PostMappingpublicResponseEntity<String>handleAlarm(@RequestBodyList<AlarmMessage>alarms){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_token=YOUR_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?key=YOUR_KEY6.4 Slack通知
slackHooks:-url:https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK6.5 通知渠道配置对比图
+------------------------------------------------------------------+ | 告警通知渠道对比 | +------------------------------------------------------------------+ | | | 渠道 | 配置复杂度 | 到达率 | 适用场景 | +------------------------------------------------------------------+ | Webhook | ⭐⭐⭐ | 自定义 | 自定义告警处理流程 | | DingTalk | ⭐⭐ | ★★★★ | 国内企业团队首选 | | WeChat | ⭐⭐ | ★★★★★ | 微信办公场景 | | Slack | ⭐⭐ | ★★★★ | 国际化团队/国外企业 | | Feishu | ⭐⭐ | ★★★★ | 飞书用户 | +------------------------------------------------------------------+7. 告警静默与分级
7.1 静默期(silence-period)
silence-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{privateMap<String,Long>suppressedServices=newConcurrentHashMap<>();publicbooleanshouldSuppress(AlarmMessagealarm){// 如果上游服务已告警,抑制下游StringserviceName=alarm.getName();Stringupstream=getUpstream(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原生暂不支持 │ | | │ 可通过Prometheus+AlertManager │ | | │ 结合实现动态阈值 │ | | └────────────────────────────────┘ | +------------------------------------------------------------------+8.4 生产环境完整告警配置示例
# alarm-settings.yml 生产级配置rules:# ========== 服务级别 ==========service_resp_time_rule:metrics-name:service_resp_timeop:">"threshold:1000period:10count:3silence-period:30message:"[P3] 服务 {name} 平均响应时间 {value}ms"service_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}ms"instance_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_token=xxxsecret:xxx9. 总结
SkyWalking的告警系统像一位不知疲倦的哨兵:
- 指标选得好:从服务、端点、数据库到JVM,覆盖所有关键维度
- 规则配得巧:period + count组合找到灵敏度与噪音的平衡
- 通知发得准:Webhook/钉钉/企微/Slack多通道,分级通知
- 静默设得稳:silence-period防止告警风暴
把告警想象成你手机的"勿扰模式"——重要电话(P0/P1)永远不静音,普通通知(P3)按你的节奏来。
下一篇文章,我们将回到一个看似"传统"但非常重要的场景——SkyWalking在单体应用中的应用,看看这个"云原生时代的APM"如何在"老系统"中发光发热。
上一篇【第21篇】用SkyWalking排查慢服务——从蛛丝马迹到真相大白
下一篇【第23篇】SkyWalking与单体应用——老系统也能焕发新活力