微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

能否允许 Messenger 的消耗命令从 SQS 消息读取失败中恢复?

如何解决能否允许 Messenger 的消耗命令从 SQS 消息读取失败中恢复?

我正在处理 a simple microservice,我们已将它们放在一起排队并发送电子邮件。在实时环境中,队列目前通过最新的 Symfony Messenger 组件 (v5.2.x) 及其 SQS 桥使用 SQS。

这通常运行良好,但偶尔(大约每隔几周)我们会看到 SQS 向使用者/工作人员返回一个流氓 500 服务器错误,这是一个运行 Messenger 的现成的 ECS 服务 ConsumeMessagesCommand .该错误导致消费者完全退出 - 不是 ECS 启动另一个世界末日,但感觉我们应该能够做得更好!

我查看的最后一个跟踪是使用 Messenger v5.1.5,但我认为所涉及的 Messenger 代码自那以后没有发生实质性变化。错误来自 AmazonSqsReceiver::get() on this line,消费者应用程序崩溃报告 PHP Fatal error: Uncaught AsyncAws\Core\Exception\Http\ServerException。我在这个问题的底部粘贴了带有日志时间戳的完整跟踪。

由于 ServerException implements HttpException 被捕获,据我所知,代码接下来会抛出一个 Symfony 原生的 TransportException,但传入原始 AWS 异常以供 Messenger 处理,因为它认为合适 –然后有些东西(我还没有完全弄清楚)似乎稍后会重新抛出它,导致致命的未处理异常

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

快速浏览了将 AmazonSqsReceiver 扩展为仅调整 get() 而无需维护完全独立的 Receiver,但由于 Connection 之类的属性是私有的,因此很快就会变得混乱。

>

我认为我在错误情况下的理想结果是要么

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

  • 失败会抛出 TransportException 但这会将消息 ID 放入某种失败/死信队列中,以便通过原始接收器使用的相同连接进行 X 次重试——但我不确定 Messenger 是否重新-排队模型是这样工作的,当消息在消费者中获取本身失败时?感觉就像我们可能没有必要的信息以有组织的 Messenger 队列方式重新排队,如果我们无法读取超出我们要求 SQS 的 ID 的消息详细信息。

任何想法都非常感谢 - 关于这是否按设计运行,以及如果是这样我可以做些什么来解决它!

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/sqsaws-async/core(特别是 v1.7.0 or newer of the latter)来解决这个问题,而无需更改 Symfony Messenger 本身。

在我尝试在 PR 中修补 Messenger 之后,@jderusse(我认为他在上述库上工作过)suggested 这应该通过使用 RetryableHttpClient 来解决问题。

由于 lib 的标准重试策略 includes repeating failed calls that get HTTP 500 responses,这似乎应该可以捕获边缘情况,并且可能是最佳解决方案。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。