Postfix 队列卡在 deferred:退避参数、relayhost 吞吐与 transport 分 lane
现象
新邮件迟迟进不了 active 队列,maillog 里同一批 queue ID 反复 deferred,所有投递进程都卡在连不可达站点上。容易走的弯路是把 queue_run_delay 调小,或者反复 postqueue -f。官方 TUNING_README 对此有明确警告:提高重试频率或频繁 flush deferred 队列,投递性能可能反而变差。
排查前先分清三件事:邮件是被 4xx 退避、被 5xx 退信,还是根本没建立起 SMTP 连接。
三类失败的处理路径
4xx(421/450/451/452,含灰名单):进指数退避循环,累计到 maximal_queue_lifetime(默认 5d)后退信。
5xx:通常直接对该收件人退信,不进退避。
连接层失败(TCP 超时、握手失败):不产生 4xx,走 default_destination_concurrency_failed_cohort_limit 的 dead 判定。该参数默认 1,只统计连接/握手失败,不统计 4xx,成功投递后计数重置。一个「伪队列」连接失败就可能把整个目的地判为 dead 并暂停投递。
另外 delay_warning_time 默认 0h,即不发「投递延迟」通知,发件人在第 5 天前收不到任何「已延迟」提醒;它不影响重试,也不影响队列寿命。
退避参数与默认值
参数默认值自 Postfix 2.4 起生效,2.4 之前 queue_run_delay 与 minimal_backoff_time 是 1000s。
| 参数 | 默认值 | 含义 |
|---|---|---|
queue_run_delay | 300s | qmgr 扫描 deferred 队列的间隔 |
minimal_backoff_time | 300s | 一封 deferred 邮件最短冷却时间,也是不可达目的地留在 dead 列表的最短时间 |
maximal_backoff_time | 4000s | 投递失败后最长冷却时间 |
maximal_queue_lifetime | 5d | 临时错误累计超过该时长即判定不可投递并退信;设 0 表示首次失败立即退回 |
bounce_queue_lifetime | 5d | MAILER-DAEMON 退信本身的存活时间 |
transport_retry_time | 60s | qmgr 联系「故障的投递 transport 进程」的间隔,与 4xx 无关 |
qmgr_message_recipient_limit | 20000 | 内存数据结构大小,同时限制短期 dead 目的地列表长度,装不下的目的地不进列表 |
delay_warning_time | 0h | 即不发投递延迟通知 |
约束关系:`queue_run_delay # 单封邮件的队列文件与最后一次失败信息
qshape deferred # 按域名与年龄看 deferred 分布
postqueue -f # flush,慎用
postsuper -r ALL # 重排队列并重置计时
配合 maillog 按 queue ID 追踪完整投递链路。
## 用 transport 分 lane
把 master.cf 的服务名当参数前缀,写在 main.cf:
```ini
# main.cf
smtp-fast_destination_concurrency_limit = 100
smtp-slow_destination_rate_delay = 20s
smtp-slow_destination_concurrency_failed_cohort_limit = 10
transport_maps 负责把收件地址映射到 (transport, next-hop)。并发与限速相关默认值:
initial_destination_concurrency5:同一目的地初始并发,之后按 TCP 慢启动式反馈增长;default_destination_concurrency_limit20:同一目的地最大并发,smtp/lmtp/pipe/virtual 通用;local_destination_concurrency_limit2:同一本地收件人并发,投递到同一 mailbox 必须串行;default_destination_recipient_limit50:单次投递最大收件人数,设为 1 会把「目的地」从域名变成收件人,同时改变并发与 rate_delay 的语义;default_destination_rate_delay0s:同一目的地两次投递之间的延迟,非零时该 transport 实际按一封一封的节奏发出;default_transport_rate_delay0s(3.1+):不区分目的地,按整个 transport 限速,例如smtp_transport_rate_delay = 20s即每分钟最多 3 封;default_destination_concurrency_failed_cohort_limit1;default_process_limit100:投递进程总数上限;qmgr_message_active_limit20000:活跃队列上限。
官方提示:rate_delay 非零时应把 transport_destination_concurrency_failed_cohort_limit 设为 10 以上,避免一次连接错误就让该目的地所有邮件被 defer。rate_delay 的计时器由 qmgr 维护,状态不跨 postfix reload / stop。需要看细节时开 destination_concurrency_feedback_debug = yes。
边界说明
- relayhost 单点 N=1 的换算是按官方公式推得,文档只给了 2 MX 的算例,实际吞吐还受对端限速、TLS 握手与 DNS 影响。
- dead 列表长度受
qmgr_message_recipient_limit(20000)限制,装不下的目的地不会进列表,这条上限对大规模多目的地场景的实际影响需要在目标版本上实测。
文档:、、。