通用面试:HTTP 423 Locked 如何设计可恢复的资源锁?
题干与适用场景
一个支持 WebDAV 的协作文件服务允许客户端编辑同一资源。写入、移动或删除时偶发返回 423 Locked。请说明 423 与 409、403 的边界,如何取得和提交锁令牌,如何处理深度锁、超时、续租和持有者崩溃,并设计可观测的恢复路径。
面试官考察点
- 能否把 423 解释为目标资源当前被锁,不能泛化成所有并发冲突。
- 是否理解 Lock-Token、If、Timeout 和 UNLOCK 的组合语义。
- 能否设计租约、断线恢复和权限校验,避免永久锁或误释放他人锁。
- 是否会让客户端区分可等待、需重新获取锁和不可重试的失败。
回答前需要澄清的问题
- 锁是 WebDAV 写锁,还是业务层编辑租约,是否两者都存在?
- 锁覆盖单个资源还是深度为 infinity 的集合,子资源如何继承和排除?
- 锁令牌存在哪里,是否与租户、主体、资源版本和权限绑定?
- 客户端断线、进程崩溃和时钟漂移时,谁负责续租与回收?
- 代理是否会重试写请求,客户端是否能安全重放?
30 秒回答框架
423 表示请求目标被当前锁阻止,重点是资源锁定状态,不是通用的权限拒绝或所有版本冲突。我会先确认锁的范围、持有者和剩余租期,再要求客户端在 If 条件中提交对应 Lock-Token。锁采用服务端租约和单调时间,续租必须鉴权,过期由服务端回收;持有者崩溃后等待租约自然结束。客户端把 423 视为受控等待或重新获取锁的信号,不对非幂等写操作盲目重试。
分步骤深入解答
第一步:划清 423 的协议边界
RFC 4918 将 423 用于请求方法无法应用于被锁定的资源。403 关注权限,409 关注当前状态与请求冲突;因此应先判断阻断来自锁、授权还是业务版本条件。
第二步:定义锁的身份与范围
锁记录至少包含资源标识、锁根、深度、所有者、令牌、创建时间、租期、权限域和资源版本。深度锁可能覆盖子资源,服务端必须在写入前解析继承关系,不能只检查 URL 自身。
第三步:校验 Lock-Token
客户端通过 LOCK 获得令牌,后续写、移动或删除请求在 If 条件中携带该令牌。服务端比较令牌、资源范围、主体和租户;令牌缺失、格式错误或属于其他锁时返回可诊断的失败,但不泄露其他租户的持有者信息。
第四步:用租约处理超时与续租
Timeout 是期望值,不应让客户端单方面决定永久有效期。服务端以单调时钟保存到期时间,续租前再次鉴权并限制最大租期;响应返回实际授予的超时,客户端按实际值安排续租。到期后锁自动失效,避免崩溃造成永久阻塞。
第五步:处理断线与恢复
持有者重连时先查询锁状态,再用仍有效的令牌续租;不能仅凭本地缓存宣称自己仍持有锁。服务端重启要从持久化存储恢复租约,若无法证明安全恢复,应让锁失效并要求客户端重新获取,防止旧令牌误写。
第六步:区分等待和重试
客户端可以显示持有者不可见的“资源正在编辑”状态,按退避查询剩余租期。423 不是网络瞬态错误;写请求只有在确认令牌、版本和请求体可重放时才重试。代理层不得对未知执行结果的非幂等请求自动重放。
第七步:观测与安全控制
记录资源哈希、锁范围、租约剩余时间、失败原因、主体哈希和请求 ID;按租户、资源类型和客户端版本统计 423 率、平均持锁时间、续租失败和过期回收。限制深度锁数量、最大租期和令牌尝试次数,防止锁耗尽与令牌猜测。
高质量示范回答
我会先确认 423 真的是 WebDAV 锁阻断,并区分 403 权限拒绝和 409 业务状态冲突。锁服务持久化资源、深度、主体、租户、Lock-Token、实际租期和版本。客户端用 LOCK 获取令牌,在 If 条件中提交;服务端同时校验令牌、范围、主体和权限。租约使用服务端单调时钟,续租受最大租期限制,断线后只能用仍有效的令牌重新确认,崩溃则等待到期自动回收。客户端把 423 显示为可恢复的编辑占用,按剩余租期退避查询,不对未知执行结果的写操作盲目重试。生产监控 423 率、持锁时长、续租失败、过期回收和深度锁数量,并用多客户端竞争、重启、时钟漂移和代理重试测试恢复路径。
常见错误
- 把所有并发冲突都返回 423,掩盖版本条件或权限问题。
- 只在内存保存锁,进程崩溃后留下永久锁或错误释放他人锁。
- 接受客户端要求的无限 Timeout,未返回服务端实际租期。
- 只比较令牌字符串,不校验资源范围、租户和主体权限。
- 让代理自动重放带副作用的写请求,造成重复修改。
追问及应对
423 与 409 何时分别使用?
资源因有效锁而拒绝方法时使用 423;没有锁但请求与当前版本或状态冲突时使用 409。两者都需要可诊断的恢复建议,不能互相替代。
深度为 infinity 的锁如何避免误伤?
限制深度锁的权限和数量,解析锁根到目标资源的继承链,并在移动、复制和删除时重新计算覆盖范围。跨租户或跨集合操作要显式拒绝,不能默认继承。
持有者崩溃后能立即强制解锁吗?
只有具备明确管理员权限和审计理由时才允许强制解锁。普通客户端等待租约到期;强制操作要使旧令牌失效并记录操作者、原因和资源版本。
服务端时钟不一致怎么办?
租约过期判断使用单节点或共识存储中的单调时间,客户端只依据响应中的实际剩余时间。跨节点续租要有版本条件,避免两个节点同时延长同一把锁。