突然红屏的那个晚上
9月3号晚上11点,我正准备睡觉,手机突然收到一堆报警。打开一看,Claude API 503、GPT 404、Gemini也挂了。
我做的那个AI客服工具直接全红,用户开始在群里问"是不是我网不好"。
翻了眼V2EX和推特,发现不止我一个人遇到。有人说"吓死我以为我号没了",有人已经开始怀疑是不是GPT-6逃逸了(笑)。
Downdetector上OpenAI的报告超过12000份,Claude约1200份。
当时我第一反应是等官方恢复。结果等了一个多小时,Claude陆续恢复了,但GPT的Codex后端还在404。
更要命的是,谁也不知道下次什么时候又炸。
没有运维团队时你能做什么
大厂可以搞多云备份、异地容灾、实时切换。个人开发者没那个条件,也没那个预算。
但总不能每次API炸了就干等着,或者半夜爬起来手动切换吧。
我当时想的很简单:不追求完美,只要"主力API挂了之后,服务至少还能撑一阵"就行。具体来说就是三件事:
- **监控API状态** - 别等用户来骂才知道挂了
- **缓存常见问答** - 重复问题直接从本地拿,不走API
- **降级逻辑托管** - 主力挂了自动切备用方案,不用人工介入
听起来很朴素,但落地的时候每一步都有坑。
第一步:写个监控脚本
最开始我想用现成的监控服务,后来发现要么太贵,要么响应不够快。干脆自己写一个。
核心逻辑就是定时ping几个主力API,记录响应时间和状态码。如果连续3次失败,就触发告警并标记为"不可用"。
用Python在线运行环境可以直接验证逻辑,不用本地装环境。
import requests
import time
from datetime import datetime
API_ENDPOINTS = {
"claude": "/ai-market-guide/market/664/
"gpt": "/ai-market-guide/market/664/
"gemini": "/ai-market-guide/market/664/
}
MAX_RETRIES = 3
TIMEOUT = 10
def check_api(name, url, headers):
failures = 0
for attempt in range(MAX_RETRIES):
try:
start = time.time()
response = requests.get(url, headers=headers, timeout=TIMEOUT)
latency = (time.time() - start) * 1000
if response.status_code < 500:
print(f"[{datetime.now()}] {name} OK - {latency:.0f}ms")
return True
else:
failures += 1
except Exception as e:
failures += 1
print(f"[{datetime.now()}] {name} ERROR - {str(e)}")
if failures < MAX_RETRIES:
time.sleep(2)
print(f"[{datetime.now()}] {name} DOWN - 连续{MAX_RETRIES}次失败")
return False这个脚本每分钟跑一次,把结果写进SQLite。挂了就发企业微信通知。
虽然简陋,但至少我能在用户骂之前知道出事了。
第二步:用LanceDB缓存高频问题
监控只能告诉你"API挂了",不能让服务继续跑。真正能撑住的是缓存。
我的应用里有大概30%的问题是重复的,比如"怎么退款""支持哪些支付方式"这种。这些问题完全可以提前用LanceDB知识库做向量索引,API挂了直接从本地查。
具体做法:
- 把历史对话里高频问题提取出来,人工review一遍答案
- 用embedding模型(我用的text-embedding-3-small)转成向量
- 存进LanceDB,查询时做相似度匹配
import lancedb
from openai import OpenAI
client = OpenAI()
db = lancedb.connect("./cache.lance")
def cache_qa_pair(question, answer):
embedding = client.embeddings.create(
input=question,
model="text-embedding-3-small"
).data[0].embedding
table = db.open_table("qa_cache")
table.add([{
"question": question,
"answer": answer,
"vector": embedding
}])
def search_cache(query, threshold=0.85):
embedding = client.embeddings.create(
input=query,
model="text-embedding-3-small"
).data[0].embedding
table = db.open_table("qa_cache")
results = table.search(embedding).limit(1).to_list()
if results and results[0]["_distance"] < (1 - threshold):
return results[0]["answer"]
return None实测下来,命中率能到40%左右。虽然不高,但关键时刻能顶一阵。
而且LanceDB是本地存储,API全挂了也不影响查询。
第三步:智能体托管降级逻辑
监控和缓存都有了,还差最后一步:自动切换。
我的思路是把降级逻辑本身做成一个AI智能体开发任务。智能体会:
- 定时检查各API的可用状态
- 收到用户请求时,先查LanceDB缓存
- 缓存未命中,按优先级尝试可用API
- 所有API都挂了,返回预设的兜底回复
这样我就不用盯着监控手动切了。智能体会根据实时状态自动决策,哪个能用用哪个。
class FallbackAgent:
def __init__(self):
self.api_status = {}
self.priority = ["claude", "gpt", "gemini"]
def update_status(self):
# 从监控脚本读取最新状态
for api in self.priority:
self.api_status[api] = check_api_status(api)
def handle_request(self, user_input):
# 1. 先查缓存
cached = search_cache(user_input)
if cached:
return {"source": "cache", "answer": cached}
# 2. 按优先级尝试API
for api in self.priority:
if self.api_status.get(api) == "available":
try:
response = call_api(api, user_input)
return {"source": api, "answer": response}
except:
self.api_status[api] = "unavailable"
# 3. 兜底回复
return {
"source": "fallback",
"answer": "当前服务繁忙,请稍后重试或联系人工客服"
}这个智能体跑在VicroCode上,可以直接调用平台的模型中心API。主力挂了就切备用模型,备用也挂了就走缓存,实在不行就兜底。
那天晚上的实际效果
搭完这套东西已经凌晨3点了。第二天早上又遇到一次小规模波动,Claude API延迟飙到10秒+。
监控脚本第一时间发了告警,智能体自动把流量切到了GPT。缓存命中了大概35%的请求,剩下的走备用API。
用户那边基本无感,只有几个人反馈"今天回复好像慢了点"。
说实话这套方案离"高可用"还很远。缓存覆盖率不够高,降级逻辑也比较粗暴,embeddings模型本身还是依赖API。
但对个人开发者来说,能做到"主力挂了不至于全红",已经够用了。
几个实战踩坑
**坑1:监控频率别太高** 一开始我设的是每10秒ping一次,结果自己把API quota打爆了。后来改成1分钟一次,配合状态缓存,基本够用。
**坑2:LanceDB的相似度阈值要调** 刚开始设的0.9,结果几乎没有命中。后来降到0.85才正常。
不同场景的阈值差异挺大,需要根据实际数据调整。
**坑3:兜底回复别写"系统错误"** 用户看到"系统错误"会以为是bug,容易引起恐慌。我改成"当前服务繁忙"之后,投诉明显少了。
**坑4:embedding也会挂** 有一次OpenAI的embedding接口抽风,导致缓存查询全失败。后来我把历史embedding结果也存了一份,至少老数据还能查。
这套方案的边界
这不是银弹。它解决不了"所有API同时长时间宕机"的情况,也扛不住突发的流量洪峰。
但它能做到的是:
- 把"服务完全不可用"变成"服务降级但还能用"
- 把"半夜爬起来手动切换"变成"早上起来看日志"
- 把"用户骂完才知道挂了"变成"挂了立刻收到通知"
对没有专职运维的个人开发者来说,这已经是性价比很高的方案了。
如果让我重新做一次
我会:
- 更早建立缓存,而不是等API炸了才想起来
- 把常见问题的标准答案提前人工review,而不是直接用历史对话
- 准备至少3个不同厂商的备用API,避免单点依赖
- 定期做故障演练,而不是真出事了才发现配置有问题
最后说一句,9月3号那晚不是个例。市场资料里有人提到,做Agent平台时"设计上没有把可用性赌在单点上"。
这句话看着像废话,但真遇到集体宕机时,才会理解它的价值。
你的应用有降级方案吗?还是也在裸奔?