跳到主要内容

生产环境最佳实践

本节定位

前面这一章我们已经分别讲了:

  • 架构
  • 运行时
  • 恢复
  • 成本

这一节要做的,是把它们收成一套真正能执行的生产 checklist。

因为很多系统不是死在“不会写”,而是死在:

  • 没有灰度
  • 没有回滚
  • 没有告警
  • 没有人知道出事时该看哪

所以这里的重点是:

把 Agent 从“能上线”推进到“可运维、可回滚、可审计”。

学习目标

  • 理解生产环境里最关键的发布与运维原则
  • 学会设计最小上线前检查清单
  • 理解灰度、回滚、告警和人工接管的作用
  • 通过可运行示例建立生产 readiness 检查思路

一、上线前真正要确认什么?

1.1 功能正确只是最基础的一层

生产 readiness 至少还包括:

  • 是否可观测
  • 是否可回滚
  • 是否有限流和超时
  • 是否有安全边界
  • 是否有评估基线

1.2 一个很实用的判断

如果某个服务上线后出了事,你是否已经知道:

  • 去哪里看日志
  • 看哪些指标
  • 如何切回旧版本
  • 谁来人工接管

如果这些问题答不上来,系统通常还没准备好进生产。


二、生产环境最重要的六条原则

2.1 先灰度,不要全量直上

Agent 系统的不确定性通常比普通 CRUD 更高。
灰度能让你先观察:

  • 正确率变化
  • 延迟变化
  • 成本变化

2.2 始终保留回滚路径

没有回滚,就没有真正安全的发布。

2.3 关键能力必须有人工接管方案

特别是:

  • 高风险操作
  • 写操作
  • 外部副作用类任务

2.4 先定义告警,再谈上线

至少要明确:

  • 哪些指标异常要告警
  • 谁接告警
  • 触发后第一步查什么

2.5 所有关键动作都应可审计

尤其是:

  • 工具调用
  • 权限判断
  • 关键状态变更

2.6 发布要和评估绑定

上线不是“相信模型”,
而是“让评估和线上信号共同说话”。


三、先跑一个最小 readiness 检查器

下面这个示例会模拟一套上线前检查。
它不会直接部署服务,而是回答:

  • 现在这套系统是否具备最基础的生产条件
deployment_config = {
"has_metrics": True,
"has_structured_logs": True,
"has_timeout": True,
"has_retry_policy": True,
"has_rate_limit": False,
"has_eval_suite": True,
"has_canary_rollout": True,
"has_rollback_plan": True,
"has_human_override": False,
"has_audit_log": True,
}


def readiness_check(config):
required = [
"has_metrics",
"has_structured_logs",
"has_timeout",
"has_retry_policy",
"has_eval_suite",
"has_canary_rollout",
"has_rollback_plan",
"has_audit_log",
]

missing_required = [key for key in required if not config.get(key, False)]
warnings = []

if not config.get("has_rate_limit", False):
warnings.append("missing_rate_limit")
if not config.get("has_human_override", False):
warnings.append("missing_human_override")

ready = len(missing_required) == 0
return {
"ready": ready,
"missing_required": missing_required,
"warnings": warnings,
}


print(readiness_check(deployment_config))

3.1 这个示例最重要的启发是什么?

它提醒你:

  • 生产 readiness 不是一种感觉
  • 而是一组可检查条件

3.2 为什么把“缺失项”显式列出来很重要?

因为这样团队讨论就会从:

  • “好像差不多了”

变成:

  • “现在缺 rate limit 和 human override”

这会让上线决策更清楚。


四、灰度发布为什么对 Agent 尤其重要?

4.1 因为 Agent 的问题 often 是概率性的

有些问题不会在本地固定复现,
而是在真实流量里才暴露,例如:

  • 某类复杂输入触发错误路线
  • 某工具在高并发下表现不稳
  • 某些 prompt 在边缘样本上失控

4.2 灰度的核心收益

  • 先少量流量验证
  • 保留旧系统兜底
  • 在真实环境中收集指标

4.3 一个很简单的流量分配示意

def route_request(request_id, canary_ratio=0.2):
bucket = sum(ord(c) for c in request_id) % 100
return "new_agent" if bucket < canary_ratio * 100 else "stable_agent"


for request_id in ["req-001", "req-002", "req-003", "req-004"]:
print(request_id, "->", route_request(request_id))

这段代码虽然简单,但它体现了:

  • 灰度并不神秘
  • 本质上就是受控流量分配

五、回滚为什么必须提前设计?

5.1 回滚不是出事后临时想办法

如果系统一出问题才开始想:

  • 切回哪个版本
  • 状态怎么恢复
  • 数据副作用怎么处理

通常已经太晚。

5.2 回滚至少要回答三件事

  1. 怎么切回旧版本
  2. 新版本产生的中间状态怎么处理
  3. 是否需要暂停高风险动作

5.3 为什么 Agent 回滚比普通页面更复杂?

因为它可能已经产生了:

  • 工具调用副作用
  • 持久化状态
  • 外部系统写入

所以回滚不仅是“切镜像”,
还要考虑状态一致性。


六、告警和人工接管怎么配合?

6.1 告警不是越多越好

关键是:

  • 告警要能触发具体动作

例如:

  • 超时率 > 5%
  • 熔断连续打开
  • 成本突然偏离正常区间

6.2 人工接管不是系统失败,而是系统成熟

在高风险系统里,
人工接管说明你承认:

  • 自动化不是无边界的

这反而更像成熟设计。

6.3 常见接管方式

  • 转人工客服
  • 暂停写操作
  • 切换只读模式
  • 要求人工审批

七、最容易踩的误区

7.1 误区一:上线前只做功能自测

没有评估、观测、回滚和灰度,
功能自测远远不够。

7.2 误区二:只有安全系统才需要审计

很多普通业务 Agent 也会涉及:

  • 用户数据
  • 写操作
  • 外部副作用

审计一样重要。

7.3 误区三:生产最佳实践就是一张 checklist

checklist 很重要,
但它真正有用的前提是:

  • 团队知道谁负责
  • 出事时真的会执行

小结

这节最重要的是建立一个生产观:

Agent 的生产 readiness,不是“功能跑通”就结束,而是必须同时具备灰度、回滚、告警、审计和人工接管这些保障机制。

只有这些机制在,系统才配得上“生产环境”这四个字。


练习

  1. 根据你现在的项目,列一版自己的 readiness 配置表,看看缺哪些项。
  2. 为什么说灰度发布对 Agent 比对静态页面更重要?
  3. 如果某个高风险工具调用开始异常增多,你会优先做告警、熔断,还是人工接管?为什么?
  4. 想一想:回滚为什么不只是“把代码切回上一个版本”?