php连接重试需按http、数据库、队列类型及错误场景分别配置:http重试针对网络超时和5xx,禁用4xx重试;数据库仅对连接断开类异常生效,需pdo异常模式+break_reconnect;队列重试由$tries与retry_after协同控制;所有重试必须区分错误类型、设2~3次上限、加100ms以上间隔并避免雪崩。

HTTP请求重试(Guzzle/Stripe/curl)
对网络层不稳定或服务端瞬时故障最有效,但必须区分错误类型:
- Guzzle:不靠全局timeout,要分层设超时参数——connect_timeout(1–3秒)、timeout(略大于后端SLA,如3秒)、read_timeout(大文件下载用);重试只针对连接拒绝、超时、5xx、CURLE_COULDNT_CONNECT等,GET/HEAD默认可重试,POST需配合idempotency key
-
Stripe SDK:直接调用
\Stripe\Stripe::setMaxNetworkRetries(3)即可启用,默认已覆盖超时、连接失败、5xx、409及stripe-should-retry: true响应头 -
原生curl:用
for循环 +usleep(100000)(100ms)控制间隔;检查curl_errno()(如CURLE_OPERATION_TIMEOUTED)、curl_error()非空、HTTP状态码是否为5xx;避免对4xx(如401、404)重试
数据库连接重试(PDO/MySQLi/ThinkPHP)
仅对连接断开类异常生效(如MySQL server has gone away),语法错误或事务中失败不会触发:
-
PDO:在DSN中加
connect_timeout=5,或选项数组里设PDO::MYSQL_ATTR_CONNECT_TIMEOUT => 5;必须开启PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,否则异常被静默吞掉 -
MySQLi:创建连接后立即调用
mysqli_options($conn, MYSQLI_OPT_CONNECT_TIMEOUT, 5);建议搭配mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)捕获异常 -
ThinkPHP:核心是配置
'break_reconnect' => true,但仅对PDOException有效;事务内失败不会自动重连,需手动重试并重新开启事务;Swoole长连接环境需监听onClose事件重建连接
队列任务重试(ThinkPHP/Laravel风格)
重试由驱动层和任务类共同控制,retry_after ≠ tries:
-
retry_after(config/queue.php):单次任务最长执行时间,超时即判失败,例如
'retry_after' => 60 -
$tries(任务类属性):决定最多重试几次,如
public $tries = 3;若不定义,默认为0(无限重试) -
驱动限制:database驱动不支持
$tries,必须用Redis/Beanstalkd等支持原子操作的驱动;失败日志记录需显式启用'failed' => ['driver' => 'database'] -
退避策略:ThinkPHP默认无延迟,失败后立刻重试;高频任务建议在
handle()中根据$this->attempts()手动加usleep()或使用delay()错峰
通用原则与避坑点
无论哪种连接,重试都必须守住三条线:
- 只重试可恢复错误:网络抖动、连接超时、5xx、服务临时不可用;不重试4xx、SQL语法错误、主键冲突、权限不足等业务错误
- 必须带指数退避或固定间隔:如100ms → 200ms → 400ms,或统一100–500ms,避免雪崩式重试压垮下游
- 重试上限严格控制:一般2~3次足够,再失败应告警而非继续硬扛;关键路径(如支付回调)建议结合异步补偿或人工介入流程
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











