预警比告警早 23 分钟:时序异常检测与大模型辅助的故障预警实践

预警比告警早 23 分钟:时序异常检测与大模型辅助的故障预警实践 预警比告警早 23 分钟时序异常检测与大模型辅助的故障预警实践一、 从告警到预警思维模式的转变1.1 告警和预警的区别维度告警 (Alert)预警 (Warning)触发条件阈值超标趋势异常发现时机故障已发生故障即将发生信息量CPU 90%CPU 过去 30 分钟持续上升紧急程度需要立即响应可以评估后处理价值止损预防1.2 预警系统的架构flowchart TD A[Prometheus] -- B[时序异常检测] B -- C[预警事件] C -- D[LLM 分析引擎] D -- E[严重性判断] E -- F[P0/P1: 实时通知] E -- G[P2/P3: 聚合日报]核心差异在于预警系统不依赖阈值而是通过机器学习检测数据的趋势变化和模式偏离。二、 时序预警检测的三层模型2.1 第一层短周期趋势检测5-15 分钟窗口# short_trend_detector.py — 短周期趋势检测 import numpy as np from sklearn.linear_model import LinearRegression class ShortTrendDetector: 短周期趋势检测捕捉 5-15 分钟内的变化趋势 def detect_trend(self, series: np.ndarray) - dict: 检测短期趋势 X np.arange(len(series)).reshape(-1, 1) y series.values.reshape(-1, 1) model LinearRegression() model.fit(X, y) slope model.coef_[0][0] r2 model.score(X, y) # 斜率为正说明上升趋势为负说明下降 # R²越高说明趋势越显著 trend_strength abs(slope) * r2 return { slope: slope, r_squared: r2, trend_strength: trend_strength, prediction: model.predict([[len(series)]])[0][0], # 预测下一个值 direction: up if slope 0 else down, severity: high if trend_strength 0.5 else ( medium if trend_strength 0.2 else low) } # 使用示例 detector ShortTrendDetector() # 每 1 分钟检测一次 CPU 使用率的趋势 cpu_values get_metric(node_cpu_seconds_total{modeidle}, window15m) result detector.detect_trend(cpu_values) if result[direction] down and result[severity] high: # CPU 空闲率持续下降使用率持续上升 send_warning(CPU 使用率持续上升, f斜率{result[slope]:.2f}, 预测下一个值{result[prediction]:.1f})2.2 第二层周期性模式偏离检测纵向对比很多指标具有明显的周期性——比如工作日和周末的 QPS 差异很大。预警系统需要理解这种周期性# cycle_deviation_detector.py — 周期性偏离检测 class CycleDeviationDetector: 周期性偏离检测对比当前值和历史同期值 def __init__(self, prometheus_url: str): self.prom PrometheusConnect(urlprometheus_url, disable_sslTrue) def detect_deviation(self, metric: str, service: str) - dict: 检测与历史同期相比的偏离度 now datetime.now() # 当前值最近 5 分钟的均值 current_query favg_over_time({metric}{{service{service}}}[5m]) current_value self._query_one(current_query) # 上周同一天同一时段的值历史基线 last_week_start now - timedelta(days7) history_query favg_over_time({metric}{{service{service}}}[5m]) offset 1w history_value self._query_one(history_query) if history_value 0: return {deviation_pct: 0, severity: unknown} # 计算偏离度 deviation (current_value - history_value) / history_value * 100 severity high if abs(deviation) 50 else ( medium if abs(deviation) 30 else ( warning if abs(deviation) 15 else normal)) return { current: current_value, history_baseline: history_value, deviation_pct: f{deviation:.1f}%, direction: up if deviation 0 else down, severity: severity, suggested_action: self._suggest_action(metric, deviation) } def _suggest_action(self, metric: str, deviation: float) - str: 根据指标类型和偏离方向给出建议 if error_rate in metric and deviation 30: return 检查最近一次发布回滚可能存在问题的版本 elif latency in metric and deviation 30: return 检查上游服务状态和数据库连接池 elif cpu in metric and deviation 50: return 检查是否有异常进程或流量突增 else: return 建议关注持续观察 15 分钟2.3 第三层跨指标关联预警单个指标异常可能是噪声但多个指标同时异常一定是信号# cross_metric_warning.py — 跨指标关联预警 class CrossMetricWarning: 跨指标关联预警 def check_correlation(self, metrics: dict) - list: 检查多个指标之间的关联模式 warnings [] # 规则 1: 请求量正常但错误率上升 → 服务本身有问题 if (metrics[qps][deviation] 10 and metrics[error_rate][deviation] 50): warnings.append({ type: service_degradation, confidence: 0.85, message: 请求量正常但错误率飙升服务本身存在缺陷, suggestions: [检查最近代码变更, 查看错误日志分布] }) # 规则 2: 请求量上升 延迟上升 CPU 上升 → 正常扩展 if (metrics[qps][deviation] 30 and metrics[latency][deviation] 20 and metrics[cpu][deviation] 20): warnings.append({ type: normal_scaling, confidence: 0.90, message: 流量增长导致延迟和 CPU 同步上升建议提前扩容, suggestions: [提前扩容 Pod, 检查 HPA 配置是否合理] }) # 规则 3: 请求量不变 延迟上升 CPU 不变 → 线程阻塞/code issue if (abs(metrics[qps][deviation]) 10 and metrics[latency][deviation] 30 and abs(metrics[cpu][deviation]) 10): warnings.append({ type: thread_contention, confidence: 0.75, message: 请求量不变但延迟上升且 CPU 未同步上升可能有线程阻塞, suggestions: [jstack 查看线程状态, 检查数据库连接池] }) return warnings三、 LLM 辅助预警判断预警系统的最大挑战是误报率。如果预警太多团队会进入预警疲劳最终无视所有预警。我们引入 LLM 做二次判断——在预警发送前让 LLM 检查这个预警是否合理# llm_warning_filter.py — LLM 预警过滤器 class LLMWarningFilter: 用 LLM 过滤和分级预警 async def should_alert(self, warning: dict, context: dict) - dict: 判断预警是否需要发送 prompt f你是一个 SRE 预警过滤专家。请判断以下预警是否需要立即通知工程师。 ## 预警信息 - 类型{warning[type]} - 置信度{warning[confidence]} - 消息{warning[message]} ## 当前系统上下文 - 当前时间{context[current_time]} - 是否工作时间{context[is_working_hours]} - 最近是否有发布{context[recent_deploy]} - 类似预警的历史命中率{context[historical_accuracy]} ## 判断标准 1. 如果是深夜22:00-08:00且置信度 0.8 → 延迟到早上聚合发送 2. 如果预警类型在历史上误报率 50% → 标记为低优先级 3. 如果是已知的周期性波动 → 不发送 4. 如果影响核心交易链路 → 即使置信度低也要发送 请返回 - decision: send / delay / suppress - reason: 简短理由 - priority: P1/P2/P3 # 调用 LLM... result await self._call_llm(prompt) return result四、 实践效果指标使用前使用后提升提前发现故障时间0min23min (平均)∞P0 故障数量/月12558%预警总数/天-35-有效预警比例-72%-工程师对预警满意度-7.8/10-最让我们惊喜的数据是72% 的预警在 24 小时内被验证为有效。也就是说每发出 10 条预警有 7 条以上是真正有价值、需要关注的。总结从被动响应告警到主动接收预警看起来只是换个词但背后是整个运维思维模式的转变。告警告诉你已经出事了预警告诉你即将出事了。前者需要止损后者只需要预防——两者的响应成本和影响范围天差地别。部署这套预警系统半年后团队形成了一种新习惯每天早上先看预警日报了解今天可能出现的风险而不是等告警响了再去救火。预防的价值永远大于止损。