Symfony Can Messenger';是否允许s consume命令从SQS消息读取失败中恢复?

Symfony Can Messenger';是否允许s consume命令从SQS消息读取失败中恢复?,symfony,amazon-sqs,reliability,Symfony,Amazon Sqs,Reliability,我正在做我们一起排队和发送电子邮件的工作。在实时环境中,队列目前通过最新的Symfony Messenger组件(v5.2.x)及其SQS桥接器使用SQS 这基本上运行得很好,但偶尔(大约每隔几周)我们会看到SQS向消费者/工作用户返回一个rogue 500服务器错误,这是一个运行Messenger现成的ConsumeMessagesCommand的ECS服务。这一错误导致消费者完全退出——并不是世界末日,因为ECS又开始了另一个,但感觉我们应该可以做得更好 我看到的最后一个跟踪是Messeng

我正在做我们一起排队和发送电子邮件的工作。在实时环境中,队列目前通过最新的Symfony Messenger组件(v5.2.x)及其SQS桥接器使用SQS

这基本上运行得很好,但偶尔(大约每隔几周)我们会看到SQS向消费者/工作用户返回一个rogue 500服务器错误,这是一个运行Messenger现成的
ConsumeMessagesCommand
的ECS服务。这一错误导致消费者完全退出——并不是世界末日,因为ECS又开始了另一个,但感觉我们应该可以做得更好

我看到的最后一个跟踪是Messenger v5.1.5,但我认为相关的Messenger代码没有实质性的变化。错误来自,消费者应用程序崩溃,报告一个
PHP致命错误:Uncaught AsyncAws\Core\Exception\Http\ServerException
。我已经在这个问题的底部粘贴了完整的跟踪和日志时间戳

由于
ServerException实现了被捕获的HttpException
,据我所知,接下来代码会抛出一个Symfony native
TransportException
,但会传入原始的AWS异常,让Messenger根据需要进行处理——然后是一些事情(我还没有完全弄清楚这一点)似乎稍后会重新抛出,导致致命的未处理异常

感觉可能有一种不同的行为可以使用,而不是强制退出到
ConsumeMessagesCommand
,可能是通过配置一个稍微不同的接收器,或者如果一致认为其他东西对大多数用例更好的话,建议改变SQS one的处理方式。我很高兴尝试使用后者,但我觉得到目前为止,我对Messenger的一些类及其预期用途的理解有点模糊。我注意到最近添加的新的
RecoverableExceptionInterface
,但我不知道将其用于这样的接收器是否在预期范围内

我快速查看了扩展
AmazonSqsReceiver
以仅调整
get()
,而不维护完全独立的接收器,但由于
Connection
等属性是私有的,因此很快就会变得混乱

我认为我在错误案例中的理想结果是:

  • 来自SQS的单个
    HttpException
    将导致
    get()
    被重试X次,可能其间有一个可配置的暂停Y ms
  • 只有在X个连续失败之后,我们才会抛出一个
    TransportException

  • 失败会抛出一个
    TransportException
    ,但这会将消息ID放入某种失败/死信队列中,通过原始接收者使用的相同连接重试X次–但我不确定Messenger的重新排队模型是否能以这种方式工作,当消费者中的消息获取本身失败时?如果我们无法读取超出请求SQS的ID之外的消息详细信息,我们可能没有必要的信息以有组织的Messenger队列方式重新排队
任何非常受欢迎的想法–关于这是否符合设计,以及如果符合设计,我可能会做些什么来解决它

2020-11-29T09:14:04.977+02:00   [29-Nov-2020 07:14:04 UTC] PHP Fatal error: Uncaught AsyncAws\Core\Exception\Http\ServerException: HTTP 500 returned for "https://sqs.eu-west-1.amazonaws.com/".
2020-11-29T09:14:04.977+02:00   Code: InternalError
2020-11-29T09:14:04.977+02:00   Message: We encountered an internal error. Please try again.
2020-11-29T09:14:04.977+02:00   Type: Receiver
2020-11-29T09:14:04.977+02:00   Detail:
2020-11-29T09:14:04.977+02:00   in /var/www/html/vendor/async-aws/core/src/Response.php:358
2020-11-29T09:14:04.977+02:00   Stack trace:
2020-11-29T09:14:04.977+02:00   #0 /var/www/html/vendor/async-aws/core/src/Response.php(117): AsyncAws\Core\Response->getResolveStatus()
2020-11-29T09:14:04.977+02:00   #1 /var/www/html/vendor/async-aws/core/src/Result.php(63): AsyncAws\Core\Response->resolve(0.1)
2020-11-29T09:14:04.977+02:00   #2 /var/www/html/vendor/symfony/amazon-sqs-messenger/Transport/Connection.php(202): AsyncAws\Core\Result->resolve(0.1)
2020-11-29T09:14:04.977+02:00   #3 /var/www/html/vendor/symfony/amazon-sqs-messenger/Transport/Connection.php(193): Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection->fetchMessage()
2020-11-29T09:14:04.977+02:00   #4 /var/www/html/vendor/symfony/amazon-sqs-messenger/Transport/Connection.php(165): Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection->getNewMessages()
2020-11-29T09:14:04.977+02:00   #5 /var/www/html/vendor/symfony/amazon-sqs-messenger/Transport/Connection.php(152): Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection->getNextMessages()
2020-11-29T09:14:04.977+02:00   #6 /var/www/html/vendor/symfony/amazon-sqs-messenger/Transport/AmazonSqsReceiver.php(44): Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection->get()
2020-11-29T09:14:04.977+02:00   #7 /var/www/html/vendor/symfony/messenger/Worker.php(74): Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsReceiver->get()
2020-11-29T09:14:04.977+02:00   #8 /var/www/html/vendor/symfony/messenger/Command/ConsumeMessagesCommand.php(197): Symfony\Component\Messenger\Worker->run(Array)
2020-11-29T09:14:04.977+02:00   #9 /var/www/html/vendor/symfony/console/Command/Command.php(258): Symfony\Component\Messenger\Command\ConsumeMessagesCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
2020-11-29T09:14:04.977+02:00   #10 /var/www/html/vendor/symfony/console/Application.php(916): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
2020-11-29T09:14:04.977+02:00   #11 /var/www/html/vendor/symfony/console/Application.php(264): Symfony\Component\Console\Application->doRunCommand(Object(Symfony\Component\Messenger\Command\ConsumeMessagesCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
2020-11-29T09:14:04.977+02:00   #12 /var/www/html/vendor/symfony/console/Application.php(140): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
2020-11-29T09:14:04.977+02:00   #13 /var/www/html/mailer-cli.php(18): Symfony\Component\Console\Application->run()
2020-11-29T09:14:04.977+02:00   #14 {main}
2020-11-29T09:14:04.977+02:00   thrown in /var/www/html/vendor/async-aws/core/src/Response.php on line 358
2020-11-29T09:14:04.981+02:00
Script php mailer-cli.php messenger:consume -vv --time-limit=86400 handling the messenger:consume event returned with error code 1

现在看来,可以通过使用最新的稳定的
aws async/sqs
aws async/core
(尤其是)来解决这个问题,而无需更改Symfony Messenger本身

在我尝试在PR中修补Messenger后,@jderusse——我认为他曾在上述库中工作过——应该通过使用
RetryableHttpClient
来解决这些漏洞

由于lib的标准重试策略,这似乎应该抓住边缘情况,并且可能是最好的修复方法


我们的开发分支上已经有了库更新,因此将优先发布实时更改以进行验证。

对我来说,在那里使用
RecoverableExceptionInterface
是有意义的。我的理解是,当预期结果无论如何都是相同的,例如不可处理的消息(例如无效的json)不需要重试时,将不会使用它,因为它将保持不可处理。这里不一定是这样,所以这是有道理的。我不确定它是否有意不使用。我认为你绝对应该在symfony/symfony中打开一个问题。AsyncAWS报告的底层服务器错误是什么?谢谢@dbrumann,很高兴听到我可能在正确的轨道上!我已经提出了根本问题,我不确定是否还有更多信息可用。看起来“我们遇到了一个内部错误…”的注释来自AWS,并且是关于他们在这些情况下提供的所有信息——我确实尝试了一个PR来实现这一点(最初由维护人员推荐了一些调整)——但在进一步的审查中,工作人员似乎不会发现这种新的异常类型。我猜它是被设计用来扔到堆栈中的其他地方的。更新aws异步库看起来是可行的,它将作为一个答案发布。哦,是的。杰里米·德鲁斯肯定知道那里发生了什么。我之前只研究了自定义处理程序和中间件,但忽略了发送者/接收者并不真正关心可重试性,但有意义的地方。如果aws async的更新解决了这个问题,我想没问题。感谢您花时间进行调查和贡献。