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秒后才会执行第一次重试)。
快速排查步骤
- 在
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 } }
- 确认
sendSms抛出的异常类型,根据需求在重试策略中配置retry_on。
内容的提问来源于stack exchange,提问作者nboulfroy
相关产品推荐
相关产品推荐

