用 AI 做联动:当应用层出现问题,网络如何被“自动拉入决策回路”

用 AI 做联动:当应用层出现问题,网络如何被"自动拉入决策回路"

搞了十几年网络,我最怕的不是设备宕机,而是凌晨两点会议室里那句小心翼翼又带点埋怨的:"应用慢了,网络那边拉个监控看看?"

那种感觉就像是在浓雾里打仗,应用层在喊疼,网络层在喊冤,中间隔着一层名为"数据孤岛"的厚壁障。大家都想联动,都想自动化,但大多数尝试最终都变成了"拿着锤子找钉子"的自嗨。

这一篇,我不谈那些宏大的 AI 原理,也不画 PPT 上的架构大饼。我想聊聊在几次生产事故的"毒打"后,我们是如何真正让 AI 像个有经验的专家一样,在应用出事时,冷静地判断网络该不该动、怎么动。这是关于"克制"与"决策"的工程真相。

1为什么"应用出问题,网络却永远最后一个知道"

在大多数企业里,下面这个场景并不陌生。

凌晨两点,应用告警先炸了锅。

接口 p95 延迟翻倍,错误率开始爬升,APM 面板一片红色。

应用团队开始排查:

是不是代码?是不是数据库?是不是缓存雪崩?

十几分钟后,排查没有明确结论,于是他们抛出一句熟悉的话:"你们网络有没有问题?"网络工程师被拉进会议,打开监控系统,看接口、看丢包、看 CPU。大多数时候,答案是:

"网络指标看起来都挺正常的。"于是,应用继续怀疑网络,网络继续否认,问题在两个系统之间被来回传递。

这不是谁的问题,而是体系的问题。

因为在传统架构中:

  • 应用系统只对应用负责
  • 网络系统只对链路负责
  • 二者之间,没有一个"共享的决策模型"

而 AI 真正能改变的,恰恰是这一层。

2 "联动"这两个字,99% 的人一开始就理解错了

在讨论"AI 做应用-网络联动"之前,必须先澄清一个误区。

很多人理解的联动是:

应用慢了 → 自动改 QoS

应用慢了 → 自动切路由

应用慢了 → 自动调负载均衡

这类方案,工程上并不难,

但它们有一个致命问题:因果不成立

应用慢,并不等于网络该动。

真正困难的地方不在"怎么动网络",而在于一个更根本的问题:当前这个应用问题,是否"值得"网络介入?

这句话听起来简单,但在真实工程里,它几乎决定了系统成败。

维度 传统自动化脚本 本文提出的 AI 联动系统
触发逻辑 阈值触发(if A then B) 状态空间相似度 + 因果判定
对待网络 将网络视为"命令执行器" 将网络视为"可被验证的假设"
风险控制 无或简单的白名单 风险分布评估 + 实时效果观测
核心目标 快速执行动作 寻找收益大于风险的介入点

3 一个真实案例:当"网络自动化"第一次被强制叫停

在一家金融行业客户中,我们曾尝试过一套"半自动联动"方案。

背景很典型:

  • 核心交易系统
  • 双活数据中心
  • SD-WAN 承载南北向流量
  • 应用侧有完整 APM / Trace

设计目标也很简单:

当交易接口 p95 延迟超过阈值,自动将交易流量从互联网专线切换到 MPLS 备线。第一次测试,看起来非常成功。

直到某一次真实生产事故发生。

3.1 事故发生经过

  • 交易系统延迟开始升高
  • 联动系统判定触发条件满足
  • SD-WAN 策略自动切换路径
  • 延迟并未明显改善
  • 部分长连接被重置,交易失败率反而上升

最终,系统被人工强制停用。

3.2 事后复盘的结论只有一句话

网络没有错,但也不该动。

真正的根因是:

  • 后端数据库行锁等待
  • 应用线程池阻塞
  • 网络丢包是"结果",不是"原因"

而自动化系统 把"相关性"当成了"因果性"

4 AI 联动系统真正要解决的第一个问题:因果资格判定

从那次事故之后,我们重新审视了整个问题。如果只能用一句话总结教训,那就是:

**不是每一个应用问题,都有资格让网络动手。**于是,一个新的概念被引入到系统设计中:

4.1 网络介入资格(Network Actionability)

这是一个明确、可计算、可审计的判断过程

它至少回答三个问题:

  1. 当前应用异常,与网络状态是否具有稳定因果相关性?
  2. 在历史上,类似状态下网络动作是否"曾经有效"?
  3. 网络可执行的动作,风险是否可控?

这三点,任何一点不成立,
网络就应该保持不动。

4.2 为什么这个判断必须由 AI 来做

很多人会问:

"这些规则,人工写不行吗?"

理论上可以,但工程上几乎不可行。

原因很现实:

  • 应用指标是高维、非线性的
  • 网络状态是多源、异步的
  • 历史事故是非结构化的

没有 AI,你只能写出一堆:

if 延迟 > X and 丢包 > Y then 动网络

而这,正是事故的起点。

4.3 从"规则系统"到"经验系统"的转变

AI 在这里扮演的,不是"预测未来",而是一个更朴素、也更工程化的角色:

把过去真实发生过的事故经验,变成可检索、可对比、可量化的判断依据。

这意味着,系统的核心不再是"阈值",

而是:

  • 相似性
  • 成功率
  • 风险分布

5 应用与网络第一次站在同一张"状态表"上

要做到这一点,第一步不是模型,而是数据。

5.1 应用侧:不只是延迟,而是"业务语义"

在系统中,我们从应用侧采集的,从一开始就不是"监控指标",而是业务状态信号

  • 接口 p95 / p99 延迟
  • 错误率(4xx / 5xx 区分)
  • Trace 中的关键 span 延迟
  • 服务调用拓扑变化

这些信号的共同特点是:

它们描述的是"业务是否顺畅",而不是"机器是否健康"。

5.2 网络侧:指标不是目的,而是证据

网络侧采集的数据也必须"降级理解"。

我们关心的不是:

  • 某接口速率是多少
  • 某设备 CPU 多高

而是这些指标是否能回答一个问题:

它们能否解释当前应用的异常?

因此,进入 AI 系统的网络特征,往往是这样的结构:

复制代码
network_features = {

    "loss_p95": 0.42,

    "rtt_p95": 185,

    "queue_depth_max": 91,

    "ecmp_entropy": 0.31,

    "recent_config_change": True

}

这些字段,每一个都对应着可被解释的网络现象

5.3 第一次对齐:时间,是最大的敌人

一个经常被忽略的工程细节是:应用和网络的数据,几乎从来不在同一时间轴上。

  • APM 是秒级
  • Telemetry 是亚秒或 10s
  • Flow 是分钟级

如果你不能把它们对齐, AI 得到的只会是噪声。

这一步,我们将在下一部分展开。

6 时间线对齐:为什么 80% 的联动系统死在"数据已经齐了"这一关

如果你真的做过应用与网络的联合排障,就会知道一件事:

"数据都在"这句话,几乎从来都是假的。

APM 有数据,Telemetry 有数据,Flow 有数据,但它们几乎从不在同一时间维度上说同一件事。这是联动系统最隐蔽、也最致命的问题。

6.1 一个你一定见过、但很少深究的现象

事故复盘会上,经常会看到这样的画面:

  • 应用团队展示一张延迟曲线
  • 网络团队展示一张丢包曲线

两张图被放在同一页 PPT 上,看起来似乎"高度相关"。

但如果你把时间轴拉到秒级,会发现:

  • 应用延迟开始抖动在 10:21:34
  • 网络丢包在 10:22:10 才明显出现

这中间的 30 多秒,
恰恰是因果判断最关键的时间窗

人脑在复盘时会自动"对齐它们",但 AI 不会------它只会把错位的数据当成噪声。

6.2 为什么简单的时间对齐几乎一定失败

很多系统第一反应是:

"那就统一成 10 秒粒度不就好了?"

这在工程上听起来很合理,但在真实环境里会引出三个问题:

  1. 应用异常是突发的,而网络指标往往是滞后的
  2. Flow 天生是事后统计,而不是实时信号
  3. Telemetry 的"尖峰"在聚合后会被抹平

结果就是:你得到了一组"看起来平滑、但已经失真"的联合特征。

6.3 工程上真正可行的做法:事件驱动时间窗

在我们最终落地的系统里,时间对齐并不是"统一采样",

而是一个事件驱动的滑动窗口模型

逻辑很简单,但非常重要:

不是问"某一时刻网络怎么样",
而是问"在应用异常发生前后,网络发生了什么变化"。

因此,我们定义了三个时间窗:

  • T ₀(触发点):应用异常首次被确认的时间
  • T ₋(前置窗口):T₀ 前 N 秒(例如 120s)
  • T ₊(后验窗口):T₀ 后 M 秒(例如 180s)

所有网络特征,都必须围绕 T ₀ 重构

6.4 真实代码示例:时间窗重建(Python)

下面这段代码,是系统中"特征对齐"的核心逻辑之一(简化版):

复制代码
def build_aligned_window(app_event_ts, net_metrics, pre=120, post=180):

    window = []

    for m in net_metrics:

        if app_event_ts - pre <= m['timestamp'] <= app_event_ts + post:

            window.append(m)

    return aggregate(window)

关键不在代码本身,

而在于这个函数背后的假设

网络是否相关,必须通过"变化趋势"来判断,而不是某个静态值。

7 从指标到"状态":向量化不是压缩,而是抽象

当时间对齐完成后,下一步才轮到真正的 AI。

但在这里,很多人会再犯一个错误:

把向量化理解成"把一堆指标塞进数组"。

这是 100% 会失败的做法

7.1 AI 不需要"所有指标",它需要"状态表达"

人类工程师在排障时,其实从不看所有指标。

你会做的是:

  • 看延迟是持续升高,还是瞬时抖动
  • 看丢包是随机的,还是集中在某条路径
  • 看 ECMP 是不是突然失衡

这在你脑子里,会自然形成一句话:

"链路没有断,但正在变得不稳定。"

AI 要的,正是这句话。

7.2 网络状态向量的真实结构

在系统中,一个"网络状态向量"并不是原始指标堆叠,

而是经过统计、归一化、语义映射后的结果。

示例(简化):

复制代码
network_state_vector = [

    loss_p95_delta,

    rtt_trend_slope,

    queue_burst_score,

    ecmp_entropy_change,

    recent_change_flag

]

这里每一个维度,都对应一个可解释的工程问题

  • loss_p95_delta:丢包是否在恶化
  • rtt_trend_slope:延迟是趋势性问题还是瞬态
  • queue_burst_score:是否存在突发排队
  • ecmp_entropy_change:流量是否被挤到少数路径
  • recent_change_flag:是否刚发生过变更

7.3 应用状态向量:不是性能,而是"体验"

应用侧向量,结构也类似,但关注点不同:

复制代码
app_state_vector = [

    p95_latency_zscore,

    error_rate_delta,

    critical_span_ratio,

    dependency_fanout_change

]

注意这里的关键词是:

"变化"而不是"绝对值"

因为绝对值受业务规模影响太大,

变化,才是异常的本质。

7.4 融合向量:应用与网络第一次被"强制同框"

最终,系统使用的是一个联合状态向量

joint_vector = concat(app_state_vector, network_state_vector)

这一步的意义非常大:

从这一刻起,应用和网络在 AI 眼里,不再是两个系统,而是一个状态空间。

8 相似事故检索:AI 第一次"翻看自己的记忆"

现在,我们终于来到整个系统最像"经验"的部分

8.1 为什么不用纯分类模型

很多团队一上来就想:

"训练一个模型,直接输出'网络是否相关'。"

工程上,这是一个非常危险的选择。

原因很简单:

  • 分类模型只会给你一个结果
  • 但生产系统需要理由

当模型说"是网络问题",你必须能回答:"它为什么这么判断?"

8.2 相似性检索的工程价值

因此,我们选择的不是"直接判断",

而是先问一个更保守的问题:

历史上,有没有和现在"很像"的事故?

如果有:

  • 当时是不是网络导致?
  • 当时网络做了什么?
  • 最终有没有改善?

这不是预测,这是对齐经验

8.3 向量检索的真实用法(FAISS)

事故库中的每一次历史事件,都会被保存为:

复制代码
{

  "vector": joint_vector,

  "label": "network" or "non-network",

  "action": "sdwan_shift",

  "result": "success"

}

当新事件出现时:

D, I = faiss_index.search(current_vector, k=20)

similar_events = [history[i] for i in I[0]]

然后系统会统计三个关键量:

  • 网络因果占比
  • 网络动作成功率
  • 动作风险分布

这一步,极大降低了误判概率

9 一个反直觉但非常重要的设计:AI 可以选择"什么都不做"

在系统上线后的前三个月,我们发现一个有趣的现象:

AI 最常做出的"正确决策",是拒绝动网络。

9.1 一个真实案例:AI 主动否决网络变更

某次事故中:

  • 应用延迟明显升高
  • 网络丢包轻微上升
  • 相似检索命中 17 条历史事件

但结果是:

  • 15 条最终被认定为数据库瓶颈
  • 2 条网络变更后无明显改善

系统最终给出的结论是:

"网络介入预期收益低于风险阈值,建议不执行任何网络动作。"

事后复盘证明,这是完全正确的判断

9.2 这一步,决定了系统能否活下来

如果 AI 不具备"克制"的能力,

它迟早会因为一次错误变更而被停用。

真正成熟的联动系统,一定是:

宁可少动十次,也不能错动一次。

10 网络动作不是"命令",而是一组有代价的假设

当你走到这一步,系统已经完成了三件极其困难的事:

  • 判定了"网络是否有介入资格"
  • 找到了历史上相似的真实事故
  • 量化了网络介入的成功概率与风险区间

但真正危险的地方,从现在才开始。

因为接下来,系统不再只是"判断",

而是要对真实生产网络动手

10.1 一个被严重低估的问题:网络动作本身是有"语义"的

在很多自动化系统里,"动作"被简化成了:

执行某条命令

修改某个策略

切换某条路径

但在真实工程中,网络动作并不是"命令",

而是一个隐含假设

"我认为这样改,业务会变好,而不是变差。"

这意味着,每一个动作,都至少包含三层含义:

  1. 意图:我想改善什么?
  2. 影响面:谁会被波及?
  3. 可逆性:如果错了,能不能收回?

如果这三点不能被系统明确表达,那就不具备自动化的资格。

10.2 动作必须被结构化,而不是脚本化

在我们的系统里,不存在"直接下发配置"这种概念

所有可执行的网络动作,都被建模为一种结构体:

复制代码
{

  "action_type": "sdwan_path_shift",

  "intent": "reduce_rtt",

  "scope": ["app=trade", "region=shanghai"],

  "expected_gain": {

    "latency_p95_ms": -35

  },

  "risk": {

    "connection_reset_prob": 0.12,

    "blast_radius_score": 0.3

  },

  "rollback": {

    "method": "policy_revert",

    "ttl": 300

  }

}

这不是为了"好看",而是为了让 AI、工程师、审计系统

在同一个语义层面上讨论问题。

字段 含义 示例
Intent 意图:到底想解决什么? 降低特定路径的 p95 延迟
Scope 爆炸半径:谁会被波及? 仅限于上海分行交易流量
Observability 验证指标:怎么算改好了? 业务侧重试率下降 5% 以上

11 风险量化:为什么"成功率高"远远不够

这是一个很多团队第一次上线就踩雷的地方。

他们会说:

"这个动作在历史上 80% 都成功了。"

但真正的问题是:

那失败的 20%,代价有多大?

11.1 成功率 ≠ 可接受性

举一个真实例子。

某客户的 SD-WAN 路径切换策略:

  • 在历史上,延迟改善成功率 78%
  • 但在失败案例中:
    • 6% 导致 TCP 重置
    • 2% 触发了防火墙状态异常
    • 1% 引发了级联重试风暴

如果这是人工操作,工程师会犹豫;如果这是自动系统,它必须会拒绝。

11.2 风险不是一个数,而是一张分布

因此,系统在评估动作时,看的不是:

success_rate = 0.78

而是类似这样的结构:

复制代码
risk_profile = {

    "no_effect": 0.15,

    "minor_degradation": 0.06,

    "connection_reset": 0.02,

    "cascading_failure": 0.01

}

然后,再把它与当前业务状态叠加:

  • 是否是高峰期
  • 是否是核心交易窗口
  • 是否已有其他变更在进行

最终形成一句极其工程化的判断

"在当前业务窗口下,该动作的期望收益低于可接受风险。"

12 自动执行的前提:不是"信任 AI",而是"限制 AI"

这是一个你作为架构师必须清醒面对的事实

任何会自动下发网络变更的系统,都不应该被完全信任。

所以,我们从一开始,就没有把目标设定为"全自动"。

12.1 三段式执行模型(Execute / Observe / Commit)

所有网络联动动作,遵循同一个执行流程:

  1. Execute(试执行)
    • 只作用于最小作用域
    • 明确 TTL(例如 5 分钟)
  2. Observe(效果观察)
    • 应用侧关键指标是否改善
    • 网络侧是否出现副作用
  3. Commit / Rollback
    • 明确判断
    • 自动收敛,而不是"留在那里"

这一步的关键不是技术,

而是把"后悔权"留给系统本身

12.2 一个你一定要有的硬规则

在所有自动化系统中,我们都强制加入了一条规则:

任何一次自动网络动作,都必须能被 1 条命令完整回滚。

如果做不到这一点:

  • 不准自动
  • 不准联动
  • 不准上线

13 失败案例复盘:一次"几乎正确"的联动事故

现在,我们来看一个真实发生过、但最终被系统救回来的事故

13.1 事故背景

  • 业务:证券交易撮合
  • 时间:开盘前 15 分钟
  • 异常:撮合接口 p99 延迟抖动

系统判定结果:

  • 网络相关概率:0.62
  • 历史相似事件:23 条
  • 建议动作:
    • 调整 QoS 队列权重(非路径切换)

13.2 执行与异常

动作进入 Execute 阶段

  • QoS 策略生效
  • 延迟略有改善(约 8%)

但在 Observe 阶段

  • 应用错误率开始轻微上升
  • 并非延迟相关,而是超时重试

系统做出了一个非常关键的决定

提前回滚,而不是等 TTL 到期。

13.3 事后复盘的结论

最终确认的根因是:

  • 撮合服务的 JVM GC 抖动
  • 网络只是"放大器",不是根因

如果当时继续放任 QoS 调整:

  • 很可能掩盖问题
  • 延误真正的修复

这一次,系统没有"解决问题",

但它成功地没有制造更大的问题

14 从工程角度看:什么样的系统才配叫"联动"

写到这里,其实你已经能清楚地看到:

真正的 AI 联动系统,和"自动化脚本"完全不是一类东西。

它至少具备以下特征:

  1. 懂因果,而不是追相关
  2. 会犹豫,而不是冲动
  3. 能拒绝,而不是必须行动
  4. 可回滚、可审计、可解释

如果少了其中任何一条,

它都只是在赌。

15 写在最后:为什么这是"未来",但不是"幻想"

很多人会问:

"这种系统,现实中真的有人用吗?"

我的回答一直很保守:

用的人不多,但活下来的人,都会走到这一步。

因为当网络规模、业务复杂度、变更频率同时上升时:

  • 人的反应速度不够
  • 人的经验不可复制
  • 人的判断无法并行

而这篇文章描述的,不是"AI 很厉害",

而是:

AI 被迫承担起人类原本无法规模化承担的责任。

小结

本文实际上只回答了一个问题:

当应用出问题时,网络如何在"不添乱"的前提下,被拉入决策回路。

答案不是某个模型,也不是某条命令,

而是一整套克制、保守、可复盘的工程体系

写到最后,我想多说一句。

很多人问我,把网络的命运交给 AI 真的放心吗?其实,这套系统的本质并不是要取代人的意志,而是要把那些资深工程师在排障时"拍脑门"的直觉,转化为可量化、可审计的科学。

真正的 AI 联动,其核心魅力不在于它能跑多快,而在于它懂得在什么时候"拒绝执行"。在这个系统上线后,我们最欣慰的不是它自动修复了几次故障,而是它在无数次应用波动中,客观地为网络"洗清了嫌疑"。

网络不再是永远的背锅侠,应用也不再是盲目的求助者。这种基于数据的"坦诚对齐",或许才是业务感知网络(IBN)真正落地的第一步。

(文:陈涉川)

2025年12月20日

相关推荐
尘心cx2 小时前
前端-APIs-day3
开发语言·前端·javascript
qq_12498707532 小时前
基于springboot的智能医院挂号系统(源码+论文+部署+安装)
java·人工智能·spring boot·后端·毕业设计
gfdhy2 小时前
【c++】素数详解:概念、定义及高效实现(判断方法 + 筛法)
开发语言·c++·算法·数学建模·ai编程
youxiao_902 小时前
Docker 容器(一)
运维·docker·容器
Dargon2882 小时前
MATLAB的Simulink的While子系统(动作子系统)
开发语言·matlab·simulink·mbd软件开发
Dargon2882 小时前
MATLAB的Simulink的可变子系统(选择子系统)
开发语言·matlab
崇山峻岭之间2 小时前
Matlab学习记录08
开发语言·学习·matlab
wenxiaohai1232 小时前
在anaconda中安装cuda-pytorch
人工智能·pytorch·python·anaconda
IT·陈寒2 小时前
零配置、开箱即用:seekdb 如何成为 AI 时代的“全能嵌入式数据库”? ——基于 OceanBase seekdb 的实践体验与 AI 开发思考
数据库·人工智能·oceanbase