乐于分享
好东西不私藏

软件开发中的重试策略最佳实践

软件开发中的重试策略最佳实践

摘要

重试是分布式系统中最常见、也最容易被滥用的容错手段。它的价值在于用有限的重复尝试屏蔽瞬时故障,例如短暂网络抖动、服务临时不可用、限流、连接重建、主从切换、消费者异常退出等。但重试不是“失败了再试几次”这么简单。设计不当的重试会造成重复写入、重复扣款、消息风暴、线程池耗尽、下游雪崩和级联故障。AWS Builders Library 明确指出,重试是“自私的”:客户端通过重试消耗更多服务端资源来提高自己的成功率;当失败来自过载时,重试会让过载更严重,甚至拖慢恢复。(Amazon Web Services, Inc.[1])

本文的核心结论是:生产系统中的默认重试策略应该是“有限次数 + 单次超时 + 指数退避 + 抖动 + 幂等保护 + 重试预算 + 死信兜底”。 立即重试只能用于极短暂的瞬时错误,且最多一次;高并发分布式系统不要使用固定间隔裸重试;涉及写操作、扣费、下单、发券、发消息等副作用操作,必须先解决幂等性,再谈重试。

关键词: 重试策略、瞬时故障、指数退避、抖动、幂等性、线程池、消息队列、HTTP、gRPC、死信队列、重试风暴


1. 什么是重试?为什么要重试?不重试会怎么样?

1.1 重试的定义

重试是指一次操作失败后,在满足特定条件的前提下,由调用方、执行框架、消息中间件、RPC 框架或任务调度器再次发起同一操作,试图让原本失败的业务流程最终成功。

Microsoft Azure Retry Pattern 对重试的定义很直接:当应用连接服务或网络资源时,透明地重新尝试失败操作,以处理瞬时故障并提升应用稳定性。云环境中的瞬时故障包括短暂网络中断、服务临时不可用、服务繁忙导致的超时等。(微软学习[2])

更工程化地说,重试由四个要素组成:

要素
含义
可重试条件
哪些异常、错误码、状态码允许重试
重试边界
最多重试几次,总耗时不能超过多少
重试间隔
立即重试、固定间隔、递增间隔、指数退避、带抖动退避
失败归宿
重试耗尽后是返回失败、降级、熔断、进入死信队列,还是人工介入

判断:没有这四个要素的“重试”,都不是可靠性设计,而是碰运气。

1.2 为什么要重试?

重试的根本原因是:现代软件系统中的很多失败不是永久失败,而是瞬时失败。AWS Builders Library 指出,系统并不总是作为一个整体失败,而是经常出现部分失败或短暂失败;对这类随机性、短时性的故障,再尝试一次往往能成功。(Amazon Web Services, Inc.[3])

典型瞬时故障包括:

场景
示例
网络抖动
TCP reset、连接超时、DNS 短暂失败
服务繁忙
HTTP 503、线程池满、连接池满
限流
HTTP 429、API quota 超限
分布式切换
主从切换、leader election、broker failover
最终一致性
刚创建的资源短时间内读取不到
消费失败
消费者进程崩溃、数据库短暂不可用

Azure 官方文档也明确说,很多瞬时故障通常会自行恢复;如果应用在合适的延迟后重试,操作很可能成功。(微软学习[4])

1.3 不重试会怎么样?

完全不重试的系统通常会把短暂波动直接暴露给用户或上游系统,导致明明可以自动恢复的请求变成失败。具体表现包括:

不重试的后果
说明
可用性下降
网络抖动、临时限流、短暂 503 都会直接变成用户失败
业务补偿成本上升
本可自动成功的订单、任务、同步流程,需要人工或异步修复
链路稳定性变差
上游看到更多失败,可能触发更多告警、降级、人工介入
消息处理丢失风险增加
MQ 消费失败后如果直接 ack 或提交 offset,消息可能被跳过
用户体验变差
用户需要手动刷新、重复点击、重复提交

但是反过来,盲目重试比不重试更危险。AWS 明确提醒,如果失败原因是下游过载,重试会增加下游负载,使问题显著恶化;在一个五层调用栈中,如果每层都重试 3 次,底层数据库的请求量可能被放大到 243 倍。(Amazon Web Services, Inc.[5])

所以结论不是“必须重试”,而是:

只对瞬时故障重试;只对可幂等或可去重的操作重试;只在有限次数、有限时间、有限预算内重试。


2. 重试设计的基本原则

2.1 先设置超时,再设置重试

没有超时的重试是错误设计。AWS 指出,客户端等待请求完成期间会持续占用资源,包括内存、线程、连接、临时端口等;大量请求长时间等待会耗尽服务资源,因此客户端应该设置超时。(Amazon Web Services, Inc.[6])

Azure 也强调,重试策略必须和 timeout 一起设计;过长的 timeout 会在故障时堆积线程和连接,过短的 timeout 又会导致本可成功的操作过早失败。(微软学习[7])

正确模型是:

单次尝试 timeout < 单次业务可接受等待时间总重试耗时 <= 上游调用 deadline / SLO重试次数 * 单次 timeout + 重试间隔 <= 总预算

2.2 只重试瞬时故障,不重试确定性失败

Azure 官方建议:只有当故障是瞬时的,并且操作在重试后可能成功时才应该重试;HTTP 429 和 5xx 通常是可重试候选,而 400、401、403、404 等大多数 4xx 通常不是重试能解决的问题。(微软学习[8])

我的工程判断是:

错误类型
是否重试
原因
网络超时、连接 reset
可以
可能是瞬时网络问题
HTTP 429
可以
但必须尊重 Retry-After 或限流策略
HTTP 500/502/503/504
可以
典型服务端瞬时异常
HTTP 400
不应重试
请求参数错,重试还是错
HTTP 401/403
不应直接重试
鉴权失败,应刷新 token 或拒绝
HTTP 404
默认不重试
除非明确是最终一致性读延迟
业务校验失败
不重试
库存不足、余额不足、状态非法不是瞬时故障
非幂等写入超时
默认不重试
除非有幂等键或可确认原操作未生效

2.3 幂等性是重试的前置条件

HTTP RFC 9110 定义:如果多个相同请求对服务端产生的预期效果与单个请求相同,则该方法是幂等的;规范中 PUT、DELETE 以及安全方法是幂等的。RFC 9110 还明确说,如果方法不是幂等的,客户端不应该自动重试,除非它有办法知道请求语义实际是幂等的,或者能确认原请求从未被应用。(RFC 编辑器[9])

这条原则在业务系统中非常关键。下面这些操作如果没有幂等保护,不应该简单自动重试:

操作
风险
创建订单
重复订单
支付扣款
重复扣款
发券
重复发券
发 MQ 消息
重复消息
新增库存流水
重复流水
外部系统调用
本地失败但外部已成功

正确做法是给写操作引入:

idempotencyKey / requestId / businessNo / unique constraint / dedup table / state machine

AWS 也明确指出,带副作用的 API 如果没有幂等性就不安全;良好的 API 设计应该避免重复副作用。(Amazon Web Services, Inc.[10])

2.4 重试必须有上限,不能无限重试

Azure 官方文档明确要求不要实现无限重试,因为它通常会阻止过载资源恢复,并导致限流和拒绝连接持续更久;应该使用有限重试,或结合熔断器让服务恢复。(微软学习[11])

重试上限至少包含三层:

maxAttempts:最多尝试次数maxBackoff:最大退避间隔deadline / totalTimeout:总耗时上限

我的判断:没有总耗时上限的重试配置是不合格的。只配置 maxAttempts 不够,因为每次请求自身可能卡很久。


3. 线程池中的重试

3.1 线程池本身不等于重试机制

Java ExecutorService / ThreadPoolExecutor 的职责是执行任务,不是保证任务成功。Oracle 官方文档说明,ExecutorService.submit 会返回 Future,调用方可以用它等待完成或取消任务;Future.get() 在任务抛异常时会抛出 ExecutionException。(Oracle 文档[12])

这意味着:线程池不会因为你的 Runnable/Callable 抛异常就自动重试业务任务。 如果你用 submit() 提交任务,但从不调用 Future.get() 或不在任务内部捕获异常,失败甚至可能被悄悄吞掉,只留下日志或没有任何业务补偿。

3.2 线程池重试的三类场景

线程池里的“重试”其实分三种,不能混为一谈。

类型
触发点
本质
推荐做法
执行失败重试
Runnable/Callable 执行时抛异常
业务执行失败
捕获异常后按策略重新调度
提交失败重试
线程池队列满或已 shutdown
资源拒绝
不应盲目重试,应限流、降级或换队列
定时/延迟重试
第一次失败后延迟再执行
任务调度
使用 ScheduledExecutorService 或 MQ

Oracle RejectedExecutionHandler 文档说明,当 ThreadPoolExecutor.execute 无法接受任务时会调用拒绝处理器,原因可能是线程数或队列槽位超过边界,也可能是 executor 已关闭。(Oracle 文档[13])

所以,RejectedExecutionHandler 不是业务重试钩子,而是线程池过载或关闭时的拒绝处理钩子。 在拒绝处理器里无限 executor.execute(r) 是非常糟糕的设计,容易形成 CPU 空转、调用线程阻塞和级联雪崩。

3.3 线程池重试的正确做法

如果任务失败后需要重试,优先使用延迟调度,而不是让工作线程 sleep。Oracle 文档说明,ScheduledExecutorService 可以把命令安排在指定延迟后运行,也可以周期性执行任务。(Oracle 文档[14])

推荐模型:

public final class RetriableTask implements Runnable {    private final ScheduledExecutorService scheduler;    private final int attempt;    public RetriableTask(ScheduledExecutorService scheduler, int attempt) {        this.scheduler = scheduler;        this.attempt = attempt;    }    @Override    public void run() {        try {            // Execute business logic.            doBusiness();        } catch (TransientException ex) {            if (attempt >= 3) {                // Send to failure handling path.                sendToDeadLetter(ex);                return;            }            long delayMs = calculateBackoffWithJitter(attempt);            // Re-schedule instead of blocking the worker thread.            scheduler.schedule(                new RetriableTask(scheduler, attempt + 1),                delayMs,                TimeUnit.MILLISECONDS            );        } catch (Exception ex) {            // Non-transient failures should fail fast.            sendToDeadLetter(ex);        }    }    private void doBusiness() {        // Business operation.    }    private long calculateBackoffWithJitter(int attempt) {        long base = 100L;        long max = 3000L;        long exponential = Math.min(max, base * (1L << attempt));        return ThreadLocalRandom.current().nextLong(0, exponential + 1);    }    private void sendToDeadLetter(Exception ex) {        // Persist failed task for later diagnosis or compensation.    }}

3.4 线程池重试的最佳实践结论

场景
推荐策略
不推荐策略
短暂网络调用失败
任务内部有限重试,或失败后重新调度
在线程池工作线程里长时间 sleep
队列满导致提交失败
限流、快速失败、降级、异步队列削峰
RejectedExecutionHandler 里无限重提
批处理任务失败
记录 attempt,延迟重试,最终进入失败表
进程内无限循环
用户请求链路中的异步任务
短 retry + 快速失败 + 可观测
让请求线程同步等待多轮重试
长时间重试
交给 MQ、调度系统、工作流引擎
放在线程池内存队列里

4. 消息队列中的重试

消息队列中的重试比 HTTP/RPC 更复杂,因为它涉及消息确认、offset 提交、重复投递、顺序性、死信队列和消费者幂等。

4.1 RabbitMQ 中的重试

RabbitMQ 的基础机制是 ack/nack/requeue。RabbitMQ 官方文档提醒,如果所有消费者因为瞬时条件无法处理消息而不断 requeue,会形成 requeue/redelivery loop,这种循环会消耗大量网络带宽和 CPU。(RabbitMQ[15])

因此,RabbitMQ 消费失败时不应该简单粗暴地:

basic.nack(requeue = true)

否则在数据库宕机、下游服务不可用、消费者全部失败时,消息会被疯狂重新投递,形成消费风暴。

RabbitMQ 的正确模型应该是:

消费失败  → 判断是否瞬时异常  → 记录重试次数  → 延迟重试  → 超过次数进入 DLX / DLQ

RabbitMQ 官方 Dead Letter Exchange 文档说明,消息可以被 dead-lettered,即重新发布到另一个 exchange;其中一种触发条件就是消费者使用 basic.reject 或 basic.nack 且 requeue=false。(RabbitMQ[16])

4.2 Kafka 中的重试

Kafka 的重试核心不在 broker 自动帮你无限重试消费逻辑,而在 offset 管理和消费语义。KafkaConsumer 官方文档说明,committed position 是已经安全存储的最后 offset;进程失败并重启后,consumer 会从该 offset 恢复。应用可以自动周期提交 offset,也可以手动调用 commit API 控制何时认为记录已消费。(Apache Kafka[17])

这带来一个非常关键的工程事实:

offset 提交时机
结果
处理前提交
失败后可能丢消息,at-most-once
处理后提交
失败后可能重复消费,at-least-once
处理和提交事务化
才可能接近 exactly-once,但依赖系统边界

Kafka 官方设计文档也说明,Kafka 默认有效保证 at-least-once;用户可以通过禁用生产者重试并在处理前提交 offset 实现 at-most-once,但这会带来丢消息风险。(Apache Kafka[18])

对于生产者重试,KafkaProducer 官方文档指出,启用幂等生产者后,producer retry 不会再引入重复消息;同时也提醒,如果启用了幂等生产者,应避免应用层重复发送,因为应用层重发无法被 producer 幂等机制去重。(Apache Kafka[19])

4.3 MQ 重试的分类

策略
机制
适用场景
风险
立即重投
nack/requeue 或不提交 offset
极短暂失败
容易形成 redelivery loop
阻塞重试
consumer 当前线程内 sleep 后重试
低频、短时间错误
阻塞分区/队列消费
延迟队列重试
失败消息投到延迟 topic/queue
下游短暂不可用
增加 topic/queue 复杂度
分级重试
1min、5min、30min 多级 retry topic
外部系统恢复时间不确定
运维复杂
死信队列
超过次数进入 DLQ
毒丸消息、永久失败
需要人工或补偿系统处理
停止消费
暂停 consumer / 熔断
下游整体不可用
延迟积压,但保护下游

Spring Kafka 官方文档说明,Kafka 的非阻塞重试和 DLT 通常需要设置额外 topic 并配置对应 listener;Spring Kafka 从 2.7 开始提供 @RetryableTopic 和 RetryTopicConfiguration 来简化这类基础设施。(Home[20]) 其配置文档还说,默认情况下启用非阻塞重试的推荐和最简单方式是在 @KafkaListener 方法上添加 @RetryableTopic,框架会自动配置所需 retry topic 和 DLT topic。(Home[21])

4.4 MQ 重试的最佳实践结论

我的判断是:

短暂、低成本异常:可以在消费者内做 1~2 次短阻塞重试。下游服务不可用:不要阻塞消费线程,应投递到延迟重试队列。毒丸消息:不要无限重试,必须进入 DLQ。Kafka 顺序敏感分区:谨慎使用非阻塞 retry topic,因为可能破坏局部顺序。所有消息消费:必须按 messageId / businessId 做幂等。

MQ 场景里最重要的不是“重试几次”,而是:

失败消息不能丢;重复消息不能造成业务重复;毒丸消息不能阻塞全队列;下游故障不能引发消费风暴。

5. HTTP 请求中的重试

5.1 HTTP 重试的核心:状态码 + 幂等性 + Retry-After

HTTP 重试必须首先遵守 HTTP 语义。RFC 9110 明确规定,GET、HEAD、OPTIONS、TRACE 是安全方法;PUT、DELETE 和安全方法是幂等方法。幂等方法可以在通信失败后自动重复,因为重复请求的预期效果与单次请求相同。(RFC 编辑器[22])

RFC 9110 同时要求:客户端不应自动重试非幂等方法,除非能确认该请求语义实际幂等,或者能确认原请求没有被应用。(RFC 编辑器[23])

这意味着:

HTTP 方法
默认重试建议
GET
可以重试,但要注意缓存、限流和请求成本
HEAD
可以重试
OPTIONS
可以重试
PUT
可以重试,但服务端实现必须符合幂等语义
DELETE
可以重试,但要确认删除语义幂等
POST
默认不自动重试,除非有幂等键或业务保证
PATCH
默认不自动重试,除非有幂等键或业务保证

5.2 哪些 HTTP 状态码适合重试?

状态码 / 异常
是否建议重试
说明
408 Request Timeout
可以
请求超时,可能是瞬时问题
429 Too Many Requests
可以
必须尊重限流和 Retry-After
500 Internal Server Error
可以
服务端瞬时错误
502 Bad Gateway
可以
网关或上游临时异常
503 Service Unavailable
可以
服务不可用,适合退避重试
504 Gateway Timeout
可以
上游超时
400 Bad Request
不建议
请求本身错误
401 Unauthorized
不直接重试
应先刷新凭证
403 Forbidden
不建议
权限问题
404 Not Found
默认不建议
除非明确存在最终一致性延迟
409 Conflict
视业务而定
乐观锁冲突可重试整个读改写流程
422 Unprocessable Entity
不建议
业务语义错误

RFC 6585 对 429 的定义是:用户在给定时间内发送了太多请求;响应可以包含 Retry-After,指示等待多久后再发起新请求。(datatracker.ietf.org[24]) RFC 9110 对 Retry-After 的定义是:服务端用它指示用户代理在后续请求前应该等待多久;其值可以是 HTTP-date,也可以是延迟秒数。(RFC 编辑器[25])

所以 HTTP 客户端的优先级应该是:

如果响应有 Retry-After:遵守 Retry-After否则:使用 capped exponential backoff with jitter

5.3 HTTP 重试配置建议

用户交互链路:

maxAttempts = 2~3perAttemptTimeout = 200ms~2s,取决于业务backoff = 50ms, 100ms, 200ms + jittertotalTimeout 必须小于用户体验预算

后台任务链路:

maxAttempts = 3~6backoff = capped exponential backoff with jittermaxBackoff = 10s~60s失败后进入任务表 / MQ / DLQ

支付、订单、发券等写操作:

必须有 idempotencyKey必须有服务端去重表或唯一索引客户端可以重试,但不能绕过幂等检查超时后应先查状态,再决定是否补偿

HTTP 场景最错误的实现是:

while (true) {    callHttp();}

这不是高可用,这是制造事故。


6. gRPC 请求中的重试

6.1 gRPC 重试不是简单拦截器循环调用

gRPC 官方文档说明,gRPC 的内建 retry 会保存调用历史,并在满足条件时用新的调用替换失败调用、重放调用历史;如果 RPC 收到 response header,该 RPC 就被视为 committed,之后不会再重试。(gRPC[26])

这点非常重要:gRPC retry 是协议栈内的 per-RPC retry,不应该简单用业务拦截器粗暴包一层循环。业务拦截器不了解 RPC 是否已 committed,也不了解底层 transparent retry、server pushback、retry throttling 等机制。

6.2 gRPC 默认行为

gRPC 官方文档说明,retry 默认是启用的,但没有默认 retry policy;没有配置 retry policy 时,gRPC 不能安全地重试大多数 RPC,只会做非常有限的 transparent retry,例如确认 RPC 尚未被服务端应用逻辑处理的低层竞态失败。(gRPC[27])

也就是说:

gRPC 开启 retry 功能 ≠ 你的业务 RPC 会自动按策略重试

要让业务 RPC 按预期重试,需要配置 service config。

6.3 gRPC retry policy 的核心参数

gRPC 官方文档给出的 retry policy 包含:

{  "retryPolicy": {    "maxAttempts": 4,    "initialBackoff": "0.1s",    "maxBackoff": "1s",    "backoffMultiplier": 2,    "retryableStatusCodes": [      "UNAVAILABLE"    ]  }}

gRPC 官方说明,retry 可配置最大尝试次数、指数退避、可重试状态码,并且会对 backoff delay 应用 ±20% jitter,避免大量客户端同时冲击服务端。(gRPC[28])

6.4 gRPC 重试限流

gRPC 支持 retry throttling:客户端为每个 server 维护 token count,失败 RPC 会减少 token,成功 RPC 会增加 token;当 token count 低于阈值时暂停重试,直到恢复。(gRPC[29])

这正是生产系统需要的能力。没有 retry throttling 的 gRPC 重试,在服务端过载时很容易把服务端进一步打死。

6.5 gRPC 重试建议

gRPC 场景
推荐策略
只读查询
UNAVAILABLE
 可重试,短 deadline,指数退避
幂等写入
可以重试,但必须带 requestId / idempotencyKey
非幂等写入
默认不自动重试,超时后查状态
流式 RPC
谨慎重试,尤其是双向流
用户链路
小次数、短 deadline
后台同步
更多次数、更长 backoff,但必须有总 deadline
服务端过载
启用 retry throttling,必要时熔断

gRPC service config 还支持 timeout、retry policy、hedging policy 等调用行为配置,并且这些配置可以限制到服务或方法粒度。(gRPC[30])


7. 有哪些重试策略?哪种场景应该使用哪种?

7.1 立即重试

立即重试指失败后不等待,马上再试一次。

适用场景
不适用场景
极短暂网络毛刺
下游过载
单次 packet collision 类问题
高并发系统
本地 CAS / 乐观锁轻微冲突
外部服务 5xx 持续升高

Azure 官方建议,立即重试只适合非常短暂的瞬时故障,而且不要超过一次;如果立即重试失败,应切换到指数退避或 fallback。(微软学习[31])

我的判断:生产系统里立即重试最多一次,多了就是自杀式放大流量。

7.2 固定间隔重试

固定间隔重试是每隔固定时间再试一次,例如每 3 秒一次。

适用场景
不适用场景
低并发后台任务
大规模客户端
运维脚本
高 QPS RPC
人工触发任务
限流、过载场景

固定间隔最大问题是容易同步。如果一批客户端同时失败,又都每 3 秒重试一次,就会制造周期性流量峰值。

7.3 递增间隔重试

递增间隔是 1s、3s、5s、10s 这类线性或阶梯式增长。

适用场景
说明
后台任务
比固定间隔温和
批处理
适合失败成本低、实时性要求不高的任务
简单 MQ 消费失败
可以配合 retry topic

递增间隔比固定间隔好,但在大规模分布式系统里仍不如指数退避加抖动。

7.4 指数退避

指数退避是每次失败后按指数增长等待时间,例如:

100ms → 200ms → 400ms → 800ms → 1600ms

Spring Batch 官方文档说明,瞬时失败后等待一段时间再重试通常有帮助;常见做法是使用指数增长等待时间,Spring Batch 为此提供 ExponentialBackoffPolicy。(Home[32])

指数退避适合:

场景
原因
HTTP 5xx
给下游恢复时间
gRPC UNAVAILABLE
服务实例或连接可能恢复
云服务 API 限流
降低请求频率
数据库主从切换
等待新主可用
MQ 延迟重试
避免马上重新打爆下游

7.5 截断指数退避 + 抖动

这是我认为分布式系统默认最应该采用的重试策略

Google Cloud IAM 官方建议,对安全可重试请求使用 truncated exponential backoff with introduced jitter;文档解释说,如果失败后不等待就重试,会短时间发送大量请求,可能超出配额;抖动可以避免多个客户端同步重试形成 thundering herd。(Google Cloud Documentation[33])

AWS 也强调,如果所有失败调用在同一时间退避结束后一起重试,会再次造成过载;jitter 通过在退避中加入随机性,把重试分散到不同时间。(Amazon Web Services, Inc.[34])

推荐公式:

delay = random(0, min(base * 2^attempt, maxBackoff))

这是 Full Jitter 风格,适合高并发系统。

7.6 服务端指示重试

服务端指示重试是指客户端优先服从服务端返回的等待时间。

HTTP 中典型是 Retry-After;RFC 9110 规定其值可以是 HTTP-date 或延迟秒数。(RFC 编辑器[35]) Azure 也建议,当响应包含 Retry-After header 时,应等待至少指定时长再重试,并让这个服务端信号优先于客户端本地 backoff 计算。(微软学习[36])

适用场景:

HTTP 429HTTP 503API Gateway 限流云服务配额限制服务端主动保护

7.7 重试预算

重试预算不是单个请求最多重试几次,而是限制一个进程、服务或依赖在一段时间内的总重试量。

Azure 官方建议,除了每个请求的 retry limit,还要实现 retry budget 限制进程或服务内总重试数量;否则许多并发请求各自重试几次,仍然可能压垮下游。(微软学习[37])

适用场景:

高 QPS 微服务调用共享下游调用第三方 API调用限流型云服务

我的判断:高 QPS 服务没有 retry budget,就是迟早要经历 retry storm。

7.8 熔断配合重试

熔断不是重试策略,但它是重试的刹车系统。Azure 建议,对于持续失败的操作,应使用 Circuit Breaker;当某时间窗口内失败数超过阈值时,请求立即失败,而不是继续访问失败资源。(微软学习[38])

适用场景:

下游持续 5xx连接池耗尽数据库不可用第三方 API 大面积失败

重试和熔断的关系:

少量瞬时失败:重试持续失败:熔断恢复探测:半开探测恢复成功:关闭熔断

7.9 死信队列 / 失败表

死信不是重试本身,而是重试耗尽后的归宿。Azure 建议,在所有重试尝试耗尽后使用 dead-letter queue,避免请求信息丢失,将失败工作延后处理。(微软学习[39])

适用场景:

MQ 消费失败异步任务失败订单补偿失败外部系统同步失败批处理失败

死信队列必须配套:

失败原因原始消息attempt 次数最后失败时间业务 keytraceId人工重放工具幂等保护

8. 场景选择矩阵

场景
推荐重试策略
最大次数
间隔策略
幂等要求
最终归宿
用户 HTTP 查询
短重试
2~3
立即一次 + 短指数退避 + jitter
建议幂等
返回失败/降级
用户 HTTP 写入
谨慎重试
0~2
指数退避 + jitter
必须幂等
查询状态/补偿
gRPC 查询
内建 retry policy
2~4
initialBackoff + maxBackoff + multiplier + jitter
建议幂等
返回 status
gRPC 写入
只重试幂等写
0~3
指数退避 + retry throttling
必须幂等
查状态/补偿
线程池任务
重新调度
3~5
ScheduledExecutor 延迟 + jitter
视业务
失败表
RabbitMQ 消费
延迟重试 + DLQ
3~10
多级延迟
必须消费幂等
DLQ
Kafka 消费
retry topic + DLT
3~10
非阻塞延迟 topic
必须消费幂等
DLT
数据库乐观锁冲突
短重试
1~3
立即或短退避
操作需可重放
返回冲突
第三方 API 限流
服务端指示优先
视限额
Retry-After / 指数退避
取决于 API
延迟任务
定时批处理
长退避
多次
capped exponential backoff
任务幂等
失败表/人工
支付扣款
默认不盲重试
0~1
先查状态
强幂等
对账补偿

9. 推荐的统一重试规范

一套合格的企业级重试规范应该包含以下内容。

9.1 重试前检查

1. 这个错误是瞬时错误吗?2. 这个操作是否幂等?3. 是否已经设置单次 timeout?4. 是否有总 deadline?5. 是否会和其他层重复重试?6. 是否有 retry budget?7. 重试耗尽后消息/任务去哪里?8. 是否有指标和日志?

9.2 默认策略

用户链路:  maxAttempts = 2~3  backoff = 50ms / 100ms / 200ms + jitter  totalTimeout <= 用户体验预算内部 RPC:  maxAttempts = 2~4  perAttemptTimeout 明确配置  capped exponential backoff with jitter  配合熔断、限流、重试预算MQ 消费:  本地短重试 1~2 次  失败后进入延迟 retry topic/queue  超过次数进入 DLQ/DLT后台任务:  允许更长退避  必须持久化 attempt 和状态  不要依赖进程内存保存重试状态

9.3 观测指标

Azure 官方建议记录重试次数、平均重试次数、总耗时等指标;偶发瞬时故障和重试是预期现象,但重试数持续上升通常意味着性能或可用性问题。(微软学习[40])

生产系统至少要监控:

retry_attempts_totalretry_success_totalretry_exhausted_totalretry_latency_secondsretry_budget_exhausted_totalretry_by_exceptionretry_by_status_codedead_letter_totalmessage_redelivery_totalconsumer_retry_lag

9.4 最危险的反模式

反模式
后果
无限重试
线程、连接、CPU、下游全部被拖死
没有 timeout 的重试
每次尝试都可能无限挂起
每层都重试
重试倍数爆炸
非幂等写操作自动重试
重复扣款、重复下单、重复发券
MQ 失败立即 requeue
redelivery loop
固定间隔大规模重试
同步流量峰值
在工作线程 sleep 等待重试
线程池被占满
只看单请求次数,不看全局预算
高并发下仍会压垮下游
重试耗尽后直接丢弃
数据丢失、无法补偿

10. 结论

软件开发中的重试策略,本质是用有限的额外尝试换取更高的瞬时故障容忍度。它应该被视为可靠性工程的一部分,而不是异常处理里的几行循环代码。

本文的最终判断如下:

  1. 什么是重试? 重试是在失败后按策略重新执行操作,用来处理瞬时故障、部分失败和短暂不可用。

  2. 为什么要重试? 因为网络、服务、云资源、消息系统和分布式组件都会出现短暂失败;合理重试能显著提升成功率和用户感知可用性。

  3. 不重试会怎么样? 不重试会把很多本可恢复的瞬时故障直接暴露为业务失败,但这不意味着应该盲目重试。

  4. 线程池怎么重试? 线程池不自动重试业务任务;执行失败应捕获异常并用 ScheduledExecutorService 或任务系统重新调度,提交失败则应限流、降级或拒绝,而不是在拒绝处理器里无限重提。

  5. 消息队列怎么重试? MQ 重试必须处理重复消费、offset/ack、延迟重试和死信队列。RabbitMQ 不应无限 requeue,Kafka 消费应控制 offset 提交并保证消费者幂等。

  6. HTTP 怎么重试? HTTP 重试必须遵守方法幂等性、状态码和 Retry-After。GET/PUT/DELETE 等幂等语义更适合重试,POST/PATCH 默认不应自动重试,除非业务提供幂等键。

  7. gRPC 怎么重试? gRPC 应优先使用官方 retry policy,通过 service config 配置 maxAttemptsinitialBackoffmaxBackoffbackoffMultiplierretryableStatusCodes 和 retry throttling。

  8. 哪种策略最推荐? 对现代分布式系统,默认应使用 有限次数的截断指数退避 + jitter。立即重试最多一次,固定间隔只适合低并发简单任务;MQ 长失败要走延迟重试和 DLQ;高 QPS RPC 必须加 retry budget 和熔断。

最终一句话:

重试是药,不是饭。小剂量、按处方、配合超时、幂等、退避、抖动和熔断,它能救系统;无限制、无幂等、无预算、无观测,它会把系统拖进雪崩。

[1]

Timeouts, retries and backoff with jitter: undefined

[2]

Retry pattern - Azure Architecture Center | Microsoft Learn: undefined

[3]

Timeouts, retries and backoff with jitter: undefined

[4]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

[5]

Timeouts, retries and backoff with jitter: undefined

[6]

Timeouts, retries and backoff with jitter: undefined

[7]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

[8]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

[9]

RFC 9110: HTTP Semantics: undefined

[10]

Timeouts, retries and backoff with jitter: undefined

[11]

Recommendations for handling transient faults - Microsoft Azure Well-Architected Framework | Microsoft Learn: undefined

[12]

ExecutorService (Java Platform SE 8 ): undefined

[13]

RejectedExecutionHandler (Java Platform SE 8 ): undefined

[14]

ScheduledExecutorService (Java Platform SE 8 ): undefined

[15]

Consumer Acknowledgements and Publisher Confirms | RabbitMQ: undefined

[16]

Dead Letter Exchanges | RabbitMQ: undefined

[17]

KafkaConsumer (kafka 2.5.0 API): undefined

[18]

Design | Apache Kafka: undefined

[19]

KafkaProducer (kafka 1.0.1 API): undefined

[20]

Non-Blocking Retries :: Spring Kafka: undefined

[21]

Configuration :: Spring Kafka: undefined

[22]

RFC 9110: HTTP Semantics: undefined

[23]

RFC 9110: HTTP Semantics: undefined

[24]

RFC 6585 - Additional HTTP Status Codes: undefined

[25]

RFC 9110: HTTP Semantics: undefined

[26]

Retry | gRPC: undefined

[27]

Retry | gRPC: undefined

[28]

Retry | gRPC: undefined

[29]

Retry | gRPC: undefined

[30]

Service Config | gRPC: undefined

[31]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

[32]

Retry: undefined

[33]

Retry failed requests | Identity and Access Management (IAM) | Google Cloud Documentation: undefined

[34]

Timeouts, retries and backoff with jitter: undefined

[35]

RFC 9110: HTTP Semantics: undefined

[36]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

[37]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

[38]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

[39]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

[40]

Transient Fault Handling - Azure Architecture Center | Microsoft Learn: undefined

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-05-11 00:10:32 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/603366.html
  2. 运行时间 : 0.184689s [ 吞吐率:5.41req/s ] 内存消耗:4,930.27kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=f3b229d4eaddd8135f29ab8be0ef958c
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000599s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000828s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000310s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000281s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000618s ]
  6. SELECT * FROM `set` [ RunTime:0.000224s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000639s ]
  8. SELECT * FROM `article` WHERE `id` = 603366 LIMIT 1 [ RunTime:0.000858s ]
  9. UPDATE `article` SET `lasttime` = 1778429432 WHERE `id` = 603366 [ RunTime:0.019326s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000724s ]
  11. SELECT * FROM `article` WHERE `id` < 603366 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000538s ]
  12. SELECT * FROM `article` WHERE `id` > 603366 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.006939s ]
  13. SELECT * FROM `article` WHERE `id` < 603366 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.056385s ]
  14. SELECT * FROM `article` WHERE `id` < 603366 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.011159s ]
  15. SELECT * FROM `article` WHERE `id` < 603366 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.008713s ]
0.186386s