傍晚六点,一家热门餐厅的后厨进入最忙碌的时段。领班老张站在出菜口,面前的订单像雪片一样飞来。石斑鱼卖完了、烤箱温度上不去、客人备注的“少辣”被做成了“特辣”……换作新手,早就乱成一锅粥。可老张不慌不忙:鱼没了就推荐同类菜,火候不够就催厨师再等两分钟,做错了就重做一份。他脑子里仿佛有一本“意外应对手册”——这正是我们这篇文章的主角:Agent 工具调用时的错误处理。 大模型驱动的 AI Agent,就像一个领班。它要调用各种工具:查天气、订酒店、发邮件、写数据库。工具是外部世界的接口,而外部世界永远充满意外:服务宕机、网络抖动、参数报错、格式混乱。一个成熟的 Agent,不是从不出错,而是像老张一样,面对错误能分类、能记录、能安抚用户、能换条路——这就是“兜底哲学”。本文将带你从零认识这套哲学的全部招式。

岗位关联

学会错误处理,你的 Agent 才能从“能跑通 demo”升级为“扛得住生产环境”。这是 AI 应用工程师从入门到职业化的关键一跃。

目录
  1. 可视化演示
  2. 错误分类识别
  3. 异常捕获机制
  4. 日志记录规范
  5. 错误提示设计
  6. 重试降级策略
  7. 兜底预案设计
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示工具调用错误三分类(网络/API/业务)、自动重试与指数退避策略、以及降级兜底链路七环节闭环。切换模式探索Agent错误处理的兜底哲学。

本节配有交互动效(进入视口后自动加载,约 3KB)。

工具调用错误三分类体系 网络错误:连接超时/DNS失败/TCP拒绝,请求未到达服务端 API错误:4xx客户端错误/5xx服务端错误;业务错误:响应体中error_code error_type = network | api(4xx/5xx) | business(code) 分类识别是错误处理的第一步

错误分类识别

后厨的意外五花八门。“石斑鱼卖完了”——通知客人换菜;“烤箱温度上不去”——等五分钟再试;“把少辣做成了特辣”——重做一份。领班老张的每一句决策都建立在一个动作上:先判断这是什么性质的意外。这个动作,就是错误处理的第一步,也是最重要的一步。

Agent 调用工具时面对的也是同样的问题。工具返回的 HTTP 状态码、抛出的异常、超时的提示……所有异常信息首先都要被分类。最常见的分法有四类:可重试错误(如网络瞬时抖动、服务短暂过载)、不可重试错误(如参数非法、权限不足)、超时类错误(请求发出但没等到响应)、格式类错误(响应收到了但结构不对,比如 JSON 解析失败)。分类决定策略:可重试的才值得重试,不可重试的重试一百次也是浪费。

判断错误的类型,最直接的技术手段是检查异常的类别、错误码和响应体的状态字段。比如一个 HTTP 429(限流)或 503(服务不可用)响应,通常意味着等一会儿就恢复,值得重试;而一个 HTTP 400(参数错误)响应,无论重试多少次都不会成功。理解这一点,我们就能用一个概率公式来说明“重试的意义”:

回到领班老张的视角:分类不是目的,而是为了给每一种意外匹配正确的行动。可重试的,等一等再来一次;不可重试的,别浪费感情;超时的,先确认是否真的失败;格式不对的,记录上报让对端修复。四类错误,四条路,各有各的走法。

Pn=1−(1−p)n\displaystyle P_{n} = 1 - (1-p)^{n}
这个公式用来计算“重试 n 次后至少成功一次的概率”。它告诉我们:如果单次成功率太低,盲目重试只是自我安慰。
  1. 单次成功概率 p单次调用工具有多大概率成功,就像厨师做一道拿手菜的成功率。如果十次有九次成功,p 就是 0.9。
    pp
  2. 单次失败概率 1-p单次把菜做坏的可能性。
    1−p1-p
  3. 连续失败概率 (1-p)^n连续做 n 盘全都失败的概率,这是指数级的绝望。
    (1−p)n(1-p)^n
  4. 至少成功一次概率 1-(1-p)^n给厨师 n 次机会,至少端出一盘好菜的概率。n 越大,这个值越接近 1。
    1−(1−p)n1-(1-p)^n

异常捕获机制

后厨地面上永远有油和水,经验丰富的厨师会在灶台边铺上防滑垫。领班老张深知:防滑垫不是用来“杜绝滑倒”的,而是用来“滑倒了也不至于摔断腿”的。异常捕获机制,就是 Agent 代码里的防滑垫。

在 Python 中,try-catch(准确说是 try-except)是拦截异常的基本手段。Agent 调用外部工具时,网络库可能抛超时异常,HTTP 客户端可能抛连接错误,JSON 解析可能抛格式错误——每一步都值得一个 try-except 去接住。捕获之后,再根据异常类型走不同分支,而不是让异常一路冒泡,把整个 Agent 进程打崩。这就是“拦截”的意义:把崩溃变成分支。

更进一步,成熟的 Agent 框架会定义自定义异常体系。比如 ToolTimeoutError、DataFormatError、ServiceUnavailableError,它们都继承自 ToolError 基类。这样一来,每个分支都能精确匹配异常类型,代码可读性也大大提升。同时要注意异常传播链的处理:Agent 往往需要依次调用多个工具,内层工具抛出的异常需要被包装成“带上下文信息”的新异常继续向上传播,方便上层决策。而防御式编程则是提前一步——在调用工具之前,先校验参数是否合法、格式是否符合预期,把能拦在门外的错误提前拦下,从根本上减少异常触发。

用领班的话说:防滑垫铺在三个位置——灶台边(try-catch)、通道上(异常传播链)、门口(防御式校验)。多铺一道,意外就少一分。但防滑垫只能防止摔倒,摔倒之后怎么记录、怎么对客人解释,才是接下来要解决的问题。

日志记录规范

老张有一个别人看不到的习惯:每天收工后,他都会在后厨的台账本上记几笔——今晚哪道菜出过问题、是什么原因、花了多久解决。这不是为了写工作总结,而是为了下周如果再遇到同样的意外,他能三分钟找到对策。日志系统,就是 Agent 的台账本。

一份合格的 Agent 日志,首先要做到结构化。不要写“报错了”这种模糊句子,而要输出 {"event": "tool_call_failed", "tool": "weather_api", "code": "TIMEOUT", "latency_ms": 3021}——机器可以解析,检索起来也高效。其次要有上下文追踪:一条请求从进入 Agent 到调用多个工具,整个过程应该共用一个 trace_id。这样排查问题时,就能顺着 trace_id 把散落在各处的日志串成一条完整的时间线,看清到底哪一步出了问题。

日志还要讲究级别。DEBUG 记开发细节,INFO 记正常流程,WARNING 记值得注意的单次失败,ERROR 记重试耗尽或兜底触发。级别分清楚了,告警和排查才能各取所需。最后是敏感信息脱敏:日志里不能出现用户手机号、API Key、token 等敏感字段。工具调用参数中的关键信息,写入日志前要用星号打码。否则台账记下来了,信息安全也泄露出去了。

老张的台账上,每一笔都清清楚楚:几号灶台、什么菜品、出了什么岔子、怎么解决的。Agent 的日志同样要形成这样的闭环——异常发生、记录归因、优化修复,从每一次故障中沉淀出系统的韧性。台账记好了,接下来就是怎么跟客人开口解释。

错误提示设计

客人不会关心“17 号蒸锅温度传感器读数异常”这样的技术细节。客人只想知道:我的菜要等多久?能不能换个菜?老张对客人说的话永远是“这道菜需要稍等几分钟,我帮您催一下后厨”或“这道菜今天备料不够,推荐您试试我们的招牌焖鸡”——原因清楚、建议明确、态度诚恳。Agent 面向用户的错误提示,也应该这么说。

设计错误提示的第一原则是用户友好措辞:把“{error_code: 500, stack_trace: ...}“翻译成”天气服务暂时不稳定,请稍后再试“。第二是给出错误恢复建议。比如”网络超时了,请检查网络连接后重试“——告诉用户接下来可以做什么,而不是让用户面对一个冰冷的失败。第三是状态可见反馈:如果 Agent 在重试,要明确显示”正在重试第 2 次,已等待 3 秒”,让用户感知到系统还在努力,而不是卡死。第四是隐藏技术细节:堆栈跟踪、内部 IP、数据库表名等,永远只进日志,不进用户界面。

这里有一条清晰的边界:技术细节给日志看,恢复建议给用户看。用户不是开发者,他们需要的是方向感。老张从不对客人背诵后厨的设备手册,但他一定会告诉客人“您的菜马上好”。Agent 也是一样——对外保持体面,对内保持透明。当错误已经无法通过话术掩盖时,就到了动用真刀真枪策略的时刻。

重试降级策略

如果一道菜连做两次都失败,老张会怎么做?他不会让厨师闷头做第三遍,而是先判断:是食材问题还是火候问题?有没有别的窗口能做这道菜?实在不行,推荐客人换成另一道招牌菜。这就是重试与降级的智慧——重试不是机械重复,而是有节奏、有边界的迂回。

技术上最经典的重试策略是指数退避:每次重试的等待时间按指数增长。第一次失败等 0.5 秒,第二次等 1 秒,第三次等 2 秒。这个“越来越慢”的设计是为了避免所有请求在同一时刻疯狂重试,把已经宕机的服务彻底压垮——也就是“雪崩效应”。公式如下:

除了指数退避,还有熔断器模式:当某个工具连续失败达到阈值(比如 5 次),熔断器“跳闸”,后续请求直接快速失败,不再进入重试循环。给故障服务一段冷静期,等它恢复后再逐步放行试探。熔断器与指数退避是一对黄金搭档:退避管重试节奏,熔断管全局开关。

降级则是更进一步的退让。如果主工具调用失败,Agent 可以调用备选工具——查天气的主服务挂了,就切到备用天气源;支付主通道拥塞,就切到备选支付通道。再不行,用缓存兜底:返回上一次成功获取的旧数据,虽然新鲜度差一点,但总比没有强。每一级降级都是向现实妥协,但妥协得有计划、有章法。

delayn=base×2n−1\displaystyle delay_{n} = base \times 2^{n-1}
第 n 次重试前等待的秒数。base 是初始等待时间(比如 0.5 秒),n 从 1 开始计数。
  1. 基底 delay_0(base)第一次等待的基准时间,通常取 0.5 到 1 秒之间,像厨师第一次翻锅的节奏试探。
    basebase
  2. 指数倍数 2^(n-1)随着重试次数 n 增加,等待时间翻倍。次数越多,间隔越长。
    2n−12^{n-1}
  3. 整体乘积 base×2^(n-1)两者相乘得到第 n 次重试前的实际等待秒数。
    base×2n−1base \times 2^{n-1}

兜底预案设计

菜做了三次,换了两个窗口,客人等的菜还是没有着落。这时候老张会亲自走到桌前,先给客人送上一碗热汤,然后诚恳道歉,最后端上店长的名片:“这顿算店里请,下次您来提前说,我们给您留最好的位置。”这碗热汤、这张名片,就是兜底预案。它不是解决所有问题的万能药,而是让最坏的情况也不至于失控。

Agent 的兜底预案有几件必须准备的东西。第一是默认响应:当所有工具都失败时,返回一个结构完整、内容保守的默认结果。比如天气查询失败时,返回“今日天气未知,建议出门携带雨具”,而不是让响应字段缺失导致下游解析崩溃。第二是人工接管通道:当自动处理无法解决时,把请求升级给人工客服或运维团队,同时把所有上下文打包传过去,让人能无缝续接。第三是完整性检查:兜底响应发出之前,要校验它的结构是否符合下游预期——字段齐全吗?类型对吗?宁可给保守的默认值,也不能给一个缺胳膊少腿的残缺响应。第四是告警通知:兜底一旦触发,必须立刻通知开发团队。兜底只是权宜之计,根本问题没有被消灭,团队需要被拉响警报去修复根源。

这些预案的最终目标,是提升系统的整体可用性。可用性可以用一个经典公式衡量:

老张那碗热汤的价值,不在于汤本身,而在于它稳定了局面、争取了时间、给出了交代。Agent 的兜底预案也一样——当所有防御都被击穿,最后一道防线不是任何招数,而是“让系统还在呼吸、让用户还有人管、让团队还能得到预警”的秩序感。有了这份兜底哲学,你的 Agent 才算真正成年。

A=MTBFMTBF+MTTR\displaystyle A = \frac{MTBF}{MTBF + MTTR}
系统“正常好用”的时间占总时间的比例。MTBF 是平均无故障时间,MTTR 是平均修复时间。
  1. 正常工作时间 MTBF系统两次故障之间的平均稳定运行时长,相当于后厨连续多少天太平无事。
    MTBFMTBF
  2. 故障恢复时间 MTTR从故障发生到恢复服务的平均耗时,相当于老张处理一场混乱所需的时间。
    MTTRMTTR
  3. 可用性比值 A正常工作的时间占全周期的比例。MTTR 越小,可用性越高——兜底预案的价值,正是把 MTTR 压到最低。
    MTBFMTBF+MTTR\frac{MTBF}{MTBF + MTTR}

AI 应用场景

电商导购 Agent 的库存降级

阶段:工具调用层

解决的问题:导购 Agent 实时查询库存时,库存服务可能宕机或超时。传统做法会直接报错中断对话,用户体验极差。AI 方案是:库存服务调用失败后,自动降级为读取本地缓存的最近库存快照,同时向用户提示“实时库存可能略有延迟”,并触发告警通知后端恢复。

具体案例:某电商平台的智能导购在"618"大促期间遭遇库存服务限流,Agent 自动启用缓存兜底,原本会流失的 37% 的咨询会话得以顺利完成,用户侧几乎无感知。

智能客服 Agent 的限流等待

阶段:工具调用层

解决的问题:客服 Agent 需要调用工单系统 API,高峰期遭遇 429 限流。传统做法让用户干等或直接失败。AI 方案:Agent 识别出这是可重试错误,采用指数退避策略,先回复用户“当前咨询量较大,我稍后自动为您提交工单”,随后在后台完成重试。

具体案例:某银行智能客服接入了退避重试逻辑后,工单提交成功率从 82% 提升到 99.2%,用户的平均等待焦虑感显著下降。

数据分析 Agent 的多源切换

阶段:工具调用层

解决的问题:数据分析 Agent 要聚合多个数据源,如果其中一个数据源返回格式异常,传统做法是整条分析链路崩溃。AI 方案:Agent 捕获格式错误后,自动切换到备用数据源拉取同字段数据,并在最终分析报告中标注“部分数据来自备源,置信度可能略低”。

具体案例:某券商研报生成 Agent 在交易日遇到核心行情源故障,自动切换冗余源后仍按时产出晨报,仅增加了 5 分钟的重试耗时。

Python 演示

python101 行
# -*- coding: utf-8 -*-"""Agent 工具调用错误处理演示:天气查询服务的抖动与兜底"""import jsonimport loggingimport randomimport time logging.basicConfig(    level=logging.INFO,    format="%(asctime)s %(levelname)s %(message)s",)  class ToolError(Exception):    """工具调用自定义异常基类"""     def __init__(self, message, code, retriable=False):        super().__init__(message)        self.code = code        self.retriable = retriable  class ToolTimeoutError(ToolError):    """超时错误,可重试"""     def __init__(self):        super().__init__("工具响应超时", code="TIMEOUT", retriable=True)  class DataFormatError(ToolError):    """返回数据格式错误,不可重试"""     def __init__(self):        super().__init__("工具返回数据格式异常", code="BAD_FORMAT", retriable=False)  class ServiceUnavailableError(ToolError):    """服务暂时不可用,可重试"""     def __init__(self):        super().__init__("服务暂时不可用", code="SERVICE_DOWN", retriable=True)  class WeatherTool:    """模拟外部天气工具:有 70% 概率抛出各类错误"""     def __init__(self):        self.fail_rate = 0.7     def fetch(self, city):        r = random.random()        if r < self.fail_rate:            pick = random.random()            if pick < 0.4:                raise ToolTimeoutError()            if pick < 0.7:                raise DataFormatError()            raise ServiceUnavailableError()        return {"city": city, "temp": random.randint(15, 35), "condition": "cloudy"}  class BackupTool:    """降级备选工具:返回保守的默认天气数据"""     def fetch(self, city):        return {"city": city, "temp": 24, "condition": "unknown", "cached": True}  class Agent:    """带错误处理与兜底策略的 Agent 客户端"""     def __init__(self):        self.tool = WeatherTool()        self.backup = BackupTool()        self.max_retry = 3        self.base_delay = 0.5     def call_weather(self, city):        delay = self.base_delay        for attempt in range(1, self.max_retry + 1):            try:                data = self.tool.fetch(city)                logging.info("第 %s 次调用成功: %s", attempt, json.dumps(data))                return data            except ToolError as e:                logging.warning("第 %s 次调用失败 [%s]: %s", attempt, e.code, e)                if not e.retriable or attempt == self.max_retry:                    break                time.sleep(delay)                delay *= 2        logging.info("重试耗尽,切换到兜底备选工具")        data = self.backup.fetch(city)        data["degraded"] = True        return data  if __name__ == "__main__":    random.seed(42)    agent = Agent()    result = agent.call_weather("shanghai")    print("最终结果:", json.dumps(result, ensure_ascii=False))
目的:完整呈现分类异常、可重试判断、指数退避、兜底降级四个核心机制在实际 Agent 客户端中的实现方式。
  1. class ToolError(Exception)自定义异常基类,为所有工具错误提供统一的 code 和 retriable 属性
  2. self.retriable = retriable标记“这个错误是否值得重试”,是分类逻辑的核心字段
  3. raise ToolTimeoutError()抛出携带分类信息的异常,让上层捕获后精准决策
  4. for attempt in range(1, self.max_retry + 1)控制重试次数上限,防止无限重试
  5. except ToolError as e:只捕获工具错误,其他异常继续上抛,守住异常边界
  6. if not e.retriable or attempt == self.max_retry:不可重试或次数耗尽,立即停止重试
  7. time.sleep(delay)指数退避的时间等待,给故障服务喘息空间
  8. delay *= 2等待时间翻倍,实现 0.5 秒 → 1 秒 → 2 秒的退避曲线
  9. self.backup.fetch(city)调用兜底工具,返回保守默认数据
  10. data["degraded"] = True标记兜底结果,让下游知道这份数据不是实时返回的

常见误区

误区“失败了就再试一次,多试几次总有成功的时候。重试次数设大一点,20 次不够就 50 次。”

正解无限重试是雪崩效应的头号帮凶。当大量 Agent 同时对一个已宕机的服务发起高频重试,崩溃会从一台服务蔓延到整个集群。正确的做法是设置最大重试次数,并配合指数退避让重试间隔逐步拉长。这就像后厨灶台已经起火,正确做法是拉掉电闸,而不是持续加大火力去烧。

为何常见:直觉上“再试一次”成本很低,但忽略了重试在其他系统上施加的放大效应。局部无害的一试,在全局变成海啸。

误区“反正都是报错,统一捕获统一重试就行了,没必要区分什么类型。”

正解参数错误、权限不足这类错误,重试一千次也还是同样的结果,只会白白浪费资源。只有可重试错误才值得重试。分类先行是错误处理的黄金起点——先判断“这个错误有没有重试的价值”,再决定怎么做。

为何常见:统一处理的代码写起来最短最省心,但代价是无法针对不同错误选择最优策略。错误处理的质量,恰恰体现在分类的精细度上。

误区“把错误码、堆栈、内部服务名都展示给用户,这样显得专业,用户也能帮忙排查问题。”

正解用户不是工程师,他们需要的是“发生了什么、我能做什么”。堆栈和内部 IP 应该进日志,用户界面只需要友好的原因和明确的恢复建议。把技术细节暴露给用户,既增加困惑,也可能泄露系统内部结构。老张永远不会让客人进后厨看那台坏掉的烤箱。

为何常见:开发者习惯以技术视角看待问题,误以为“信息量大=体验好”。但从接收者的角度,信息过载和不可理解,等于没有信息。

误区“反正有兜底方案,工具挂了也没关系,缓存顶上,用户无感。降级方案就是免死金牌。”

正解降级是不得已的妥协,不是为所欲为的后路。缓存数据会过期、备选工具也可能二次故障、默认响应的信息量远低于真实数据。降级触发的那一刻,告警就应该同时响起,让团队立即着手修复根源。兜底只负责“保住下限”,不负责“恢复健康”。

为何常见:兜底方案在演练时表现出色,容易让人产生虚幻的安全感,忽略了“服务已处于降级状态”这个事实本身才是危机。

误区“try-except 已经包住了异常,程序不会崩了,那就够了。日志记不记无所谓,反正用户看不到。”

正解异常被捕获只是第一步,如果它没有被记录、没有 trace_id、没有上下文,这个异常就等于在系统里凭空消失了。下次排查线上问题时,没有日志就像老张没写台账,一切只能靠猜。一份没有被记录的错误,是白错了一次。

为何常见:捕获异常那一刻,程序的“警报声”确实停了,开发者容易误以为问题已经解决。实际上问题还在暗中滋长,只等下次以更严重的方式爆发。

面试题

Q1. 以下哪种错误最适合直接重试?

单选题 · easy

  • A.请求参数格式非法
  • B.服务瞬时不可用← 正确答案
  • C.用户权限不足
  • D.API密钥已过期

答案:B。服务瞬时不可用是可重试错误,等一会儿可能就恢复。参数非法、权限不足、密钥过期属于不可重试错误,重试多少次都不会改变结果,就像菜谱本身写错了一样,换厨师也没用。

Q2. 指数退避重试的核心目的是?

单选题 · easy

  • A.提高单次请求速度
  • B.防止服务雪崩加剧← 正确答案
  • C.减少日志记录开销
  • D.增加网络请求次数

答案:B。指数退避让重试间隔逐次翻倍,本质是给故障服务留出恢复时间,避免海量重试在同一时刻涌向脆弱服务。它的目的不是加速请求,而是防止失控的重试把故障放大成雪崩——就像后厨起火时要先疏散人群,而不是让人群往里冲。

Q3. 结构化日志相比普通日志的主要优势?

单选题 · easy

  • A.体积更小更省磁盘
  • B.方便机器检索分析← 正确答案
  • C.不需要任何库支持
  • D.日志一定不会丢失

答案:B。结构化日志以 JSON 等固定格式输出,字段清晰,可以被日志系统自动检索、聚合和报警。普通日志像流水账,只能靠人肉浏览;结构化日志像台账表格,工具可以直接统计“这类错误今天出现了几次”。

Q4. 熔断器处于开启状态时的行为是?

单选题 · mid

  • A.把所有请求直接放行
  • B.快速失败拒绝调用← 正确答案
  • C.把请求转发给日志库
  • D.无条件等待超时结束

答案:B。熔断器像电路保险丝,跳闸后直接用快速失败挡住新请求,不再进入重试循环。这给故障服务一段冷静期,之后试探性地放行少量流量,若恢复则逐步关闭熔断,否则继续拦截。所有请求放行等于熔断器不存在,转发给日志库更是答非所问。

Q5. Agent 收到工具的超时响应后,最好先做什么?

单选题 · hard

  • A.无条件立刻重发请求
  • B.检查该请求是否幂等← 正确答案
  • C.立即抛给用户报错
  • D.丢弃所有异常日志

答案:B。超时不代表服务端没处理——很可能请求已生效,只是响应没送达。比如下单请求超时,服务端可能已经扣款成功。此时盲目重发会重复扣款。正确做法是先确认操作的幂等性,用 request_id 查询服务端状态,再决定是重发还是直接返回结果。这是“先沟通再行动”的领班智慧。

Q6. 设计用户错误提示时应当做到?

单选题 · mid

  • A.展示完整堆栈信息
  • B.告知原因与恢复方法← 正确答案
  • C.用红色大字警告
  • D.尽量拖延错误反馈

答案:B。用户友好提示的核心是“原因 + 下一步行动”,比如“网络不稳定,请稍后重试”。堆栈信息是给开发者的,红色大字和拖延反馈都无助于用户理解问题。老张对客人说话永远是一句听得懂的话加上一个可行的建议。

Q7. 兜底方案中“人工接管通道”的作用是?

单选题 · hard

  • A.让用户自己修改代码
  • B.复杂问题转交人来处理← 正确答案
  • C.替代所有自动化流程
  • D.删除故障工具的日志

答案:B。人工接管是自动化兜底的“最后一级机关”:当 Agent 重试耗尽、降级也无法完成用户诉求时,带着完整上下文把会话转交给人工坐席。它的目标不是替代自动化,而是接管自动化搞不定的少数疑难杂症——像店长亲自出马安抚客人并给出补偿方案。

Q8. 以下属于不可重试错误的有?

多选题 · easy

  • A.请求参数校验不通过← 正确答案
  • B.服务返回数据格式错误← 正确答案
  • C.网络连接瞬时超时
  • D.用户身份认证已过期← 正确答案

答案:ABD。参数校验不通过、数据格式错误、身份认证过期,都是“重试也没用”的错误——你不可能通过再打一次电话来修复电话号码本身的不合法。网络瞬时超时则可能是网络抖动导致的,值得在网络恢复后重试一次。

Q9. 日志记录规范通常包括哪些内容?

多选题 · mid

  • A.统一trace_id追踪← 正确答案
  • B.只记录成功请求日志
  • C.敏感字段脱敏处理← 正确答案
  • D.日志级别按场景分级← 正确答案

答案:ACD。trace_id 用于串联一次请求的完整调用链,脱敏保护数据安全,分级让 INFO/WARNING/ERROR 各司其职。只记录成功日志是大忌——失败日志恰恰是排查问题最珍贵的线索,老张的台账上记录的从来都是问题而非无事发生。

Q10. 设计兜底预案时应当考虑?

多选题 · extreme

  • A.提供合理默认响应← 正确答案
  • B.构建多级降级链路← 正确答案
  • C.保持静默不告警
  • D.确保系统状态一致← 正确答案

答案:ABD。兜底预案要保证“最坏情况下系统仍可用”:默认响应保证输出结构完整,多级降级链路像备胎一样逐级顶上,完整性检查确保兜底数据不会污染下游。静默不告警严重错误——兜底只是止血,如果团队不知情,根源问题永远不会被修复,系统会一直带病运行。