503 是「服务暂时不可用」:维护、过载、依赖挂了。配 Retry-After 告诉客户端等多久再来。
上一节的 500 是「我出 bug 了」,这一节的 503 是「我暂时不行」。 差别在「重试有没有用」——这直接决定客户端策略。
一、三个使用场景
维护:主动下线时回 503 加 Retry-After,比直接断连友好得多。
客户端知道「等会儿再来」,而不是「这站挂了」。
过载:请求量超过处理能力时,主动拒绝一部分(过载保护)。
这比让所有请求都超时好——快速失败比慢慢失败更省资源。
依赖故障:数据库连不上、上游服务挂了。严格说这更适合 502/504,但很多系统统一用 503。
二、Retry-After 怎么用
两种写法:秒数(Retry-After: 120)或 HTTP 日期(Retry-After: Wed, 21 Oct 2026 07:28:00 GMT)。
秒数更常用,因为不用算时区。
客户端拿到它就应该等到那个时间再来,而不是立刻重试。
忽略 Retry-After 的客户端会把故障放大——服务端刚从过载里缓过来,又被一波重试打死。
Demo 里服务端前两次回 503 加 Retry-After: 2,第三次回 200。
这个「前两次失败、第三次成功」的形态,就是自动重试要处理的标准局面。
三、重试必须配退避与抖动
2 → 4 → 8 → 16 → 32 秒是指数退避,五次重试累计等 62 秒。
这个数字很重要:重试不是免费的,业务上要能接受「最多等一分钟」。
光有退避还不够,还要加随机抖动(jitter):每个客户端在基准时间上随机偏移一点。
因为如果一万个客户端同时收到 503、同时等 2 秒、同时又回来,
服务端在那一刻要面对同一万个请求——惊群。加了抖动,请求就被摊平到一个时间窗里。
这三件事合起来(重试次数上限、指数退避、随机抖动)叫「退避重试」,是所有分布式客户端的标配,
缺一个都会出问题。
四、动手 Demo:两次 503 之后成功,顺带算一遍退避
服务端计数器前两次回 503 加 Retry-After: 2,第三次回 200。最后再算一遍指数退避的累计等待。
state[u'n'] += 1
if state[u'n'] <= 2:
return (u'HTTP/1.1 503 Service Unavailable',
[(u'Retry-After', u'2')], b'busy')
return (u'HTTP/1.1 200 OK', [(u'Content-Type', u'text/plain')], b'ok')
实跑输出:
--------------------------------------------------------------------
503 Service Unavailable:现在不行,等会儿再来
--------------------------------------------------------------------
第 1 次 HTTP/1.1 503 Service Unavailable(Retry-After: 2)
第 2 次 HTTP/1.1 503 Service Unavailable(Retry-After: 2)
第 3 次 HTTP/1.1 200 OK
503 的含义 服务暂时不可用:维护、过载、依赖挂了
Retry-After 告诉客户端等几秒再来(秒数或 HTTP 日期)
和 500 的区别 500 是「我出 bug 了」,503 是「我暂时腾不出手」
和 429 的区别 429 是「你请求太频繁」,503 是「我不行」
指数退避(秒) 2 → 4 → 8 → 16 → 32
累计等待 62 秒(5 次重试)
客户端遇到 503 的正确做法是**退避重试**,而且要加随机抖动,
否则所有客户端会在同一秒一起回来,把刚恢复的服务再打死一次。
这就是「惊群」——微服务里几乎所有重试都要配 jitter。
第 1 次 / 第 2 次 503(Retry-After: 2)、
第 3 次 200 OK——三次请求的状态变化就是自动重试要处理的完整剧本。
指数退避(秒)2 → 4 → 8 → 16 → 32、累计等待 62 秒(5 次重试)。
62 秒这个数是和的,不是单次——很多人算退避时只看最后一次。
和 500 的区别 500 是「我出 bug 了」,503 是「我暂时腾不出手」——所以 500 重试通常没用,
503 重试通常有用。这一条直接决定客户端策略。
30 秒实验
- 把
Retry-After改成一个 HTTP 日期字符串,看客户端能不能解析。 - 把服务端改成永久 503,看客户端重试五次之后该做什么(放弃并报错)。
- 算一算:如果加 20% 抖动,一万个客户端在第一个重试点上会分散到多宽的时间窗。
常见误区
- 「503 就是服务挂了」——是暂时不可用,可能下一秒就好。
- 「收到 503 应该立刻重试」——那会把过载放大,必须按 Retry-After 等。
- 「退避就够了,不用抖动」——所有客户端会在同一刻一起回来,形成惊群。
自测三问(点开对答案)
1. 503 与 500 的关键区别? —— 500 是服务端缺陷,重试通常无用;503 是暂时不可用,重试可能有用。 2. `Retry-After` 有哪两种写法? —— 秒数,或 HTTP 日期(RFC 1123 格式,末尾 GMT)。 3. 为什么退避要加随机抖动? —— 避免所有客户端在同一时刻一起重试,形成惊群把服务再打死一次。第四章到此结束。第五章看站在客户端和服务器中间的那些程序。
- ☐ (本章完,下一节 5.1 用单台虚拟主机实现多个域名)