国庆长假线上值班机器人:GLM 5.3 接入企业微信与报警短信智能降噪
国庆长假线上值班机器人:GLM 5.3 接入企业微信与报警短信智能降噪

国庆长假的这几天,刚好轮到我排班线上值班。对于维护着两百多个微服务、上千个容器节点的架构团队来说,长假值班往往是一场对神经耐受力的严峻考验。
平时在工位上,多块大屏常驻 Grafana看板,大家各司其职,告警响了有人顺手点开排查。但到了放假,所有告警都集中轰炸到值班人员的手机和企业微信上。仅仅是网络骨干网一次 50ms 的轻微抖动,Prometheus、Cat 和微服务健康检查组件就会在半分钟内连环触发 80 多条报警短信与群推送。
大部分告警都是瞬时恢复的“狼来了”,但你又绝不敢把群消息静音,因为你不知道哪一条夹杂在几十条抖动信息里的“订单库活跃连接数打满”是真的致命 P1 故障。长期处于这种告警疲劳(Alert Fatigue)状态,人不仅无法好好休息,更容易在真正出事时麻痹大意。
为了根治这个问题,在假期前一周,我们基于智谱 GLM 5.3 大模型与企业微信群机器人,搭了一套报警智能降噪与根因聚类服务。这几天线上稳定跑下来,手机从每天上百次震动缩减为每天 4 次高可信摘要,排查效率反而翻倍。
告警洪峰的症结与聚类思路
监控系统之所以会产生海量噪声,根本原因在于单点探测无法感知拓扑因果。
例如,底层的公共 Redis 集群由于某台宿主机网卡重置中断了 3 秒钟:
- 依赖该缓存的用户服务抛出 JedisConnectionException;
- 订单服务调用用户服务失败,抛出 DubboTimeoutException;
- 网关感知到下游响应过慢,抛出 Gateway 504 熔断告警;
- 消息队列消费者反压,积压告警被激活。
监控系统会机械地将上述 4 层的每台机器指标逐条发送给值班人员。但从架构师的视角来看,这起事件有且仅有一个事实:“底层某台 Redis 发生网络短暂抖动,导致下游链路出现连锁超时,3 秒后已自愈”。
我们设计的降噪架构逻辑非常纯粹:
- 第一步:时间窗口聚合。Alertmanager 的 Webhook 不直接外发,而是先灌入应用内部的 90 秒缓冲池。
- 第二步:拓扑与日志富化。从缓冲池捞出一批告警,提取报错堆栈摘要、受影响的应用名。
- 第三步:GLM 5.3 根因聚类。将多条原始事件打包给大模型,让其结合系统依赖关系进行归因,判断影响范围与修复建议。
- 第四步:企业微信卡片推送。同一类根因在指定静音窗口内合并更新,禁止刷屏。
核心实现:从接收聚合到大模型归因
1. Alertmanager Webhook 聚合器
首先在 Spring Boot 中暴露一个接收端点,将告警灌入基于并发安全队列的时间窗口收集器:
package com.yali.ops.alert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@RestController
@RequestMapping("/internal/alert")
public class AlertWebhookController {
private final AlertAggregationEngine engine;
public AlertWebhookController(AlertAggregationEngine engine) {
this.engine = engine;
}
@PostMapping("/receive")
public String receiveAlerts(@RequestBody AlertPayload payload) {
if (payload != null && payload.getAlerts() != null) {
engine.enqueue(payload.getAlerts());
}
return "SUCCESS";
}
}
收集器内部采用定时调度器,每隔 90 秒清空一次暂存区,打包进入聚类流程:
package com.yali.ops.alert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
@Component
public class AlertAggregationEngine {
private static final Logger log = LoggerFactory.getLogger(AlertAggregationEngine.class);
private final ConcurrentLinkedQueue<AlertItem> queue = new ConcurrentLinkedQueue<>();
private final GlmAnalysisService glmAnalysisService;
private final WeComNotificationService weComService;
public AlertAggregationEngine(GlmAnalysisService glmAnalysisService, WeComNotificationService weComService) {
this.glmAnalysisService = glmAnalysisService;
this.weComService = weComService;
}
public void enqueue(List<AlertItem> items) {
queue.addAll(items);
}
@Scheduled(fixedDelay = 90_000)
public void processBatch() {
if (queue.isEmpty()) {
return;
}
List<AlertItem> batch = new ArrayList<>();
AlertItem item;
while ((item = queue.poll()) != null) {
batch.add(item);
}
log.info("提取到报警批次,共 {} 条,开始请求 GLM 5.3 聚类分析...", batch.size());
try {
AlertSummary summary = glmAnalysisService.analyze(batch);
if (summary.isNeedNotify()) {
weComService.sendMarkdownCard(summary);
}
} catch (Exception e) {
log.error("报警分析或通知异常", e);
}
}
}
2. 构建 GLM 5.3 专家 Prompt 与结构化提取
大模型最擅长阅读凌乱但具备语义关联的文本。我们在 Prompt 中对 GLM 5.3 赋予“资深 SRE 架构师”角色,并约束其输出严格的 JSON 结构。
package com.yali.ops.alert;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class GlmAnalysisService {
private final ChatClient chatClient;
private final ObjectMapper objectMapper = new ObjectMapper();
public GlmAnalysisService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
public AlertSummary analyze(List<AlertItem> alerts) {
String alertJson;
try {
alertJson = objectMapper.writeValueAsString(alerts);
} catch (Exception e) {
alertJson = alerts.toString();
}
String systemPrompt = """
你是一位资深分布式系统 SRE 专家。
以下是在过去 90 秒内系统捕获的一批监控告警日志。
请分析这些告警之间的因果关联,完成以下任务:
1. 识别核心根因(Root Cause),过滤掉因上游超时引发的连锁下游告警;
2. 评估当前系统整体健康风险等级(P0/P1/P2/INFO);
3. 判断是否需要值班人员立即登录机器介入(如果已自动恢复或纯属网络瞬断且无业务损伤,标记 needNotify=false);
4. 给出一键排查命令建议(如检查某端口连接数、JVM 堆栈等)。
必须严格返回如下 JSON 格式,禁止任何额外前导词:
{
"severity": "P1",
"rootCause": "简明扼要的一句话根因",
"impactScope": "受影响的核心业务模块",
"status": "已自动恢复 / 持续恶化中",
"needNotify": true,
"troubleshootingTip": "推荐执行的排查命令或操作路径"
}
""";
String response = chatClient.prompt()
.system(systemPrompt)
.user(alertJson)
.call()
.content();
try {
// 清理可能包含的 markdown 标签
String cleanJson = response.replaceAll("```json", "").replaceAll("```", "").trim();
return objectMapper.readValue(cleanJson, AlertSummary.class);
} catch (Exception e) {
// 解析失败时的降级兜底:直接组装简单通知
AlertSummary fallback = new AlertSummary();
fallback.setSeverity("P2");
fallback.setRootCause("解析聚合异常,原始报警共 " + alerts.size() + " 条");
fallback.setNeedNotify(true);
return fallback;
}
}
}
3. 企业微信群卡片渲染与静音防轰炸
将降噪后的结果格式化为美观的 Markdown 消息发送到企业微信群。对于持续发生的同一根因事件,利用本地缓存进行哈希锁定,30 分钟内只更新不重报:
package com.yali.ops.alert;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class WeComNotificationService {
private final RestClient restClient;
private final String webhookUrl;
private final ConcurrentHashMap<String, Long> silenceCache = new ConcurrentHashMap<>();
public WeComNotificationService(@Value("${ops.wecom.webhook}") String webhookUrl) {
this.webhookUrl = webhookUrl;
this.restClient = RestClient.create();
}
public void sendMarkdownCard(AlertSummary summary) {
String silenceKey = summary.getSeverity() + ":" + summary.getRootCause();
Long lastTime = silenceCache.get(silenceKey);
long now = System.currentTimeMillis();
// 同一类告警在 30 分钟内静音抑制
if (lastTime != null && (now - lastTime) < 30 * 60 * 1000L) {
return;
}
silenceCache.put(silenceKey, now);
String markdown = String.format("""
### 🚨 智能值班哨兵诊断报告 [%s]
> **根因归纳**:%s
> **影响范围**:%s
> **当前状态**:%s
> **建议操作**:`%s`
*系统已自动将 90 秒内 50+ 条级联告警降噪压缩,请按需介入。*
""",
summary.getSeverity(),
summary.getRootCause(),
summary.getImpactScope(),
summary.getStatus(),
summary.getTroubleshootingTip()
);
Map<String, Object> body = Map.of(
"msgtype", "markdown",
"markdown", Map.of("content", markdown)
);
restClient.post()
.uri(webhookUrl)
.contentType(MediaType.APPLICATION_JSON)
.body(body)
.retrieve()
.toBodilessEntity();
}
}
假期线上实战复盘
在国庆假期第四天上午,这套系统打了一场极其漂亮的仗。
当天上午 10:14,机房骨干网交换机出现短时丢包。如果在过去,几十个业务微信群会同时刷出上百条 Dubbo 超时和连接断开告警,值班人员得挨个点进去看堆栈确认哪儿坏了。
而这一次,企业微信哨兵机器人在 10:16 准时推送了一条聚合卡片:
- 等级:P2(黄色预警)
- 根因:IDC 跨机房专线网络在 10:14:02 发生约 4 秒丢包,导致订单微服务调用营销中心出现 12 次超时重试。
- 状态:下游重试均已成功,链路当前已完全恢复,无数据积压。
- 建议:无需人工登录介入,保持监控观察。
看完这条卡片,我只需要扫一眼核心指标大盘确认 QPS 和错误率恢复平缓,连笔记本电脑都无需打开。
把大语言模型用在运维场景中,不一定非要去搞全自动自愈或者高大上的端到端自治。先从最折磨工程师的“告警降噪”切入,把散乱的指标重组为人看得懂的因果逻辑,就能释放巨大的生产力。技术不仅要为业务兜底,也要真正善待每一个在节假日坚守岗位的人。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)