You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony/Messenger调用Web服务遇严重异常时不重试问题排查

Symfony Messenger 未执行重试的原因分析

结合你的配置和代码,导致async_sms队列不执行重试的可能原因如下:

1. 异常被静默处理

如果OvhClientManager::sendSms方法内部捕获了Web服务调用的异常但未重新抛出,Messenger会判定消息处理成功,不会触发重试逻辑。比如方法内存在try-catch块,捕获异常后仅记录日志但不向外抛出,这种情况下处理器不会传递任何异常到Messenger组件。

2. 异常类型不在可重试范围内

Symfony Messenger默认仅对临时可恢复异常(如网络超时、服务暂时不可用)执行重试。如果sendSms抛出的是业务逻辑异常(如LogicException、InvalidArgumentException)或自定义的非临时异常,默认不会触发重试。

你可以通过在重试策略中配置retry_on参数,指定需要重试的异常类:

async_sms:
    dsn: 'doctrine://default?auto_setup=0&table_name=ec2_messenger_messages'
    options:
        queue_name: 'async_sms'
    retry_strategy:
        max_retries: 3
        delay: 30000
        multiplier: 2
        max_delay: 3600000 # 改为合理值,比如1小时
        retry_on:
            - 'Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface'
            - 'App\Exception\WebServiceTemporaryException' # 自定义临时异常类

3. 重试策略配置的潜在问题

你的max_delay设置为0,虽然官方文档说明0表示不限制最大延迟,但部分Symfony版本可能存在兼容问题,导致重试逻辑未触发。建议设置一个合理的最大延迟值(如3600000,即1小时)。

4. 数据库队列状态异常

检查ec2_messenger_messages表的字段:

  • 若retry_count已等于3,说明重试已执行完毕,消息会被标记为失败(未配置failure_transport时会留在队列但不再重试);
  • 若next_retry_at为空或时间未到,说明重试触发时间未到(你的初始延迟为30秒,需等待30秒后才会执行第一次重试)。

快速排查步骤

  1. 在SmsHandler中手动捕获并重新抛出异常,确保Messenger能感知到错误:
public function __invoke(Sms $sms): void
{
    try {
        $user = $this->userRepository->findOneBy(['id' => $sms->getAddresseeId()]);
        $companyDivision = $this->companyDivisionRepository->findOneBy(['id' => $sms->getCompanyDivisionId()]);
        $this->ovhClientManager->sendSms($sms->getContent(), $user, $companyDivision);
    } catch (\Exception $e) {
        throw $e; // 确保异常被传递到Messenger
    }
}
  1. 确认sendSms抛出的异常类型,根据需求在重试策略中配置retry_on。

内容的提问来源于stack exchange,提问作者nboulfroy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 22:16:33