题目背景
一个批量 API 依次执行校验、预留库存和创建订单。预留库存失败时,创建订单没有执行。面试官要求你设计错误响应,并解释是否应该使用 HTTP 424。
核心考察点
- 能否区分 HTTP 状态码的标准语义与团队自定义约定。
- 能否表达依赖图中的部分完成、未执行和未知结果。
- 能否把幂等键、重试条件和错误详情设计成同一份契约。
参考答案
424 的标准边界
424(Failed Dependency)由 WebDAV RFC 4918 定义,表示当前方法因为另一个操作失败而无法完成。它不是“任何下游服务报错”的通用别名。若接口不是 WebDAV,团队可以采用 424,但必须在公开契约中说明语义、客户端处理方式和兼容性。
状态码选择
412 Precondition Failed:请求带有If-Match等前置条件,但条件不成立。409 Conflict:请求与当前资源状态冲突,例如库存版本已改变。424 Failed Dependency:当前步骤明确依赖同一请求或工作流中的失败步骤,且本步骤未执行。5xx:服务端无法完成请求,原因属于服务故障,而不是可由请求关系解释的依赖结果。
不要只看依赖服务返回了 500 就机械映射为 424。先判断本请求中的业务步骤是否因此被阻断,以及客户端是否能据此采取不同动作。
响应体与状态机
建议使用 RFC 9457 Problem Details,返回稳定的 type、title、status、detail 和扩展字段,例如 blockedBy、operationId、retryable、completedSteps。扩展字段属于业务契约,必须版本化。
{
"type": "https://api.example.com/problems/failed-dependency",
"title": "Order creation was blocked",
"status": 424,
"detail": "Inventory reservation failed",
"blockedBy": "reserve-inventory",
"operationId": "op_123",
"retryable": true,
"completedSteps": ["validate-order"]
}重试与未知结果
只有 retryable=true 且使用同一幂等键时才自动重试。若连接在预留库存提交后中断,客户端不能把超时当成 424,因为服务端结果未知;应通过 operationId 查询状态。已经完成的副作用不能靠再次发送请求假装回滚,必要时要提供补偿操作。
常见误区
- 把 424 当作所有微服务错误的统一状态码。
- 只返回一段可读文本,没有稳定错误类型和操作 ID。
- 收到 424 就盲目重试,导致重复扣库存或重复创建订单。
- 用 424 掩盖服务端宕机,使监控无法区分请求阻断和平台故障。
追问方向
批量请求中可以部分成功吗?
可以,但必须逐项返回状态、幂等键和依赖关系。整批响应的 HTTP 状态只表达整体结果,不能替代每项结果;若业务要求原子性,就应明确全部回滚或全部不提交。
什么时候返回 409 而不是 424?
资源版本、库存状态等冲突属于资源当前状态问题,通常用 409。只有当前步骤因同一工作流中另一步失败而未执行时,424 才能准确表达阻断关系。
依赖服务 503 时当前请求返回什么?
若当前步骤因此无法执行且契约把它视为工作流依赖失败,可返回 424 并在详情中保留根因;若这是服务整体不可用,应返回 503,并配合 Retry-After 等服务级信号。两者要在监控和客户端策略中区分。
如何测试这份契约?
覆盖依赖成功、依赖拒绝、依赖超时、提交后网络中断、重复幂等键、部分完成和恢复查询。断言状态码、Problem Details 字段、状态机终态以及副作用次数,而不只断言 HTTP 数字。
评分标准
合格
能准确说明 424 的 WebDAV 来源,给出 409、412、5xx 的边界,并提出幂等键与未知结果查询。
良好
能设计 Problem Details 扩展字段、部分完成状态和监控分类,说明自动重试的安全条件。
优秀
能从业务原子性、依赖图、补偿流程和版本化契约解释每个选择,并指出非 WebDAV 使用 424 时的兼容性风险。
答题策略
先界定状态码的标准来源,再画出步骤状态和副作用边界;最后用一条可查询、可重试的错误契约把判断落地。
参考资料
状态码规范
- RFC 4918:WebDAV(IETF)
HTTP 语义
- RFC 9110:HTTP Semantics(IETF)
错误格式
- RFC 9457:Problem Details for HTTP APIs(IETF)