简体   繁体   English

库错误:Symfony Messenger 发生套接字错误

[英]Library error: a socket error occurred in Symfony Messenger

In my Symfony project, there is a queue message handler, and I have an error that randomly appears during the execution:在我的Symfony项目中,有一个queue message handler,我在执行过程中随机出现一个错误:

[2022-10-12T07:31:40.060119+00:00] console.CRITICAL: Error thrown while running command "messenger:consume async --limit=10". Message: "Library error: a socket error occurred" {"exception":"[object] (Symfony\\Component\\Messenger\\Exception
TransportException(code: 0): Library error: a socket error occurred at /var/www/app/vendor/symfony/amqp-messenger/Transport/AmqpReceiver.php:62)
[previous exception] [object] (AMQPException(code: 0): Library error: a socket error occurred at /var/www/app/vendor/symfony/amqp-messenger/Transport/Connection.php:439)","command":"messenger:consume async --limit=10","message":"Library error: a socket error occurred"} []

The handler executes HTTP requests that could last some seconds and the whole process of a single message could even take more than one minute if APIs are slow.处理程序执行 HTTP 个请求,可能持续几秒钟,如果 API 速度慢,则单个消息的整个过程甚至可能需要一分钟以上。 The strange thing is that the problem disappears for hours but then it randomly appears again.奇怪的是问题消失了几个小时,然后又随机出现了。 The more messages are sent to the queue, the easier it's to see the exception.发送到队列的消息越多,就越容易看到异常。

config\packages\messenger.yaml配置\包\信使.yaml

framework:
    messenger:    
        transports:
            # https://symfony.com/doc/current/messenger.html#transport-configuration
            async:
                dsn: "%env(MESSENGER_TRANSPORT_DSN)%"
                options:
                    exchange:
                        name: async_exchange
                    queues:
                        async: ~
                    heartbeat: 45
                    write_timeout: 90
                    read_timeout: 90
                retry_strategy:
                    max_retries: 0
            
        routing:
            # Route your messages to the transports
            'App\Message\MessageUpdateRequest': async

App\MessageHandler\MessageUpdateRequestHandler.php App\MessageHandler\MessageUpdateRequestHandler.php

<?php

declare(strict_types=1);

namespace App\MessageHandler;

use App\Message\MessageUpdateRequest;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class MessageUpdateRequestHandler implements MessageHandlerInterface
{

    public function __invoke(MessageUpdateRequest $message)
    {
        // Logic executing API requests...
        return 0;
    }
}

Environment环境

  • Symfony Messenger: 5.4.17 Symfony 信使:5.4.17
  • PHP: 8.1 PHP:8.1
  • RabbitMQ: 3.11.5 RabbitMQ:3.11.5

Things that I tried我尝试过的事情

  • upgrading Symfony Messenger to 5.4.17, using the fix available here ;将 Symfony Messenger 升级到 5.4.17,使用此处提供的修复程序;
  • adding the following options: heartbeat , write_timeout and read_timeout in the messenger.yaml file.messenger.yaml文件中添加以下选项: heartbeatwrite_timeoutread_timeout

Related issues/links相关问题/链接

How can I fix this issue?我该如何解决这个问题?

Regarding a socket error that occurs in Symfony Messenger, I always suggest following the step-wise approach and checking if you are missing anything.关于 Symfony Messenger 中发生的套接字错误,我始终建议遵循逐步方法并检查是否遗漏任何内容。 It should fix this type of error almost every time.它几乎每次都应该修复此类错误。 Please follow these guidelines:请遵循以下准则:

  • Verify that the RabbitMQ service is active and accessible.确认 RabbitMQ 服务处于活动状态且可访问。
  • Verify that the hostname, port, username, and password are listed in the messenger.yaml file are accurate.验证messenger.yaml文件中列出的主机名、端口、用户名和密码是否准确。
  • In the messenger.yaml file, increase the heartbeat, write timeout, and read timeout settings.messenger.yaml文件中,增加心跳、写超时、读超时设置。
  • Verify your use case to determine whether the max retries number in messenger.yaml is appropriate.验证您的用例以确定messenger.yaml中的最大重试次数是否合适。
  • Look for any.network problems that could be causing the socket error.查找可能导致套接字错误的任何网络问题。
  • Make sure your PHP version is compatible with RabbitMQ and Symfony Messenger.确保您的 PHP 版本与 RabbitMQ 和 Symfony Messenger 兼容。
  • Verify that the server's resources (CPU, Memory, and Disk) are not used up.验证服务器的资源(CPU、Memory 和磁盘)没有用完。
  • Look for any relevant error messages in the PHP error log.在 PHP 错误日志中查找任何相关的错误消息。
  • Determine whether there is a problem with the MessageUpdateRequestHandler class's logic.判断MessageUpdateRequestHandler类的逻辑是否有问题。

Tip: Still stuck?提示:仍然卡住了? Try to reproduce the error with a smaller message set and in a controlled environment to isolate the root cause that we may be missing.尝试使用较小的消息集并在受控环境中重现错误,以隔离我们可能遗漏的根本原因。

Hope it helps.希望能帮助到你。 Happy debugging and good luck.调试愉快,祝你好运。

(May not be answer, but too long for comment. I don't use Symphony so can't test, but do a lot with queues.) (可能不是答案,但评论时间太长。我不使用 Symphony,所以无法测试,但对队列做了很多。)

In this code ( https://github.com/surfingmig/symfony/blob/608f4dade49f2f0367380d37c946b4a6a3d3985c/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php ) there is no verification that the connection is still alive before the ack() ;在此代码中( https://github.com/surfingmig/symfony/blob/608f4dade49f2f0367380d37c946b4a6a3d3985c/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php )在验证连接之前仍然没有活动ack() everything is stored in locally held variables and they are only checked before get and send.所有内容都存储在本地变量中,并且仅在获取和发送之前进行检查。

I suggest you copy我建议你复制

$this->clearWhenDisconnected();

if ($this->autoSetupExchange) {
    $this->setupExchangeAndQueues(); // also setup normal exchange for delayed messages so delay queue can DLX messages to it
}

from get() into the top of the ack() function.get()ack()的顶部 function。

If that works, also copy to the nack() , purge() and countMessagesInQueues() functions, or make a common function "checkStillConnected()" then turn into a pull request.如果可行,还可以复制到nack()purge()countMessagesInQueues()函数,或者创建一个通用的 function “checkStillConnected()”,然后变成拉取请求。

Note: You will still get exceptions (there is always a gap between "am I connected", and "ack()", even if microseconds, where disconnect can happen).注意:您仍然会遇到异常(“我是否已连接”和“ack()”之间始终存在差距,即使是微秒,也可能发生断开连接)。 So a retry handler in your code as well would be appropriate.因此,您的代码中的重试处理程序也是合适的。 I try three times before giving up.在放弃之前,我尝试了三次。

(Other note: one of those change requests linked is only a stop-gap solution that triggers under certain conditions, but will miss most issues.) (另请注意:其中一个链接的变更请求只是在特定条件下触发的权宜之计解决方案,但会遗漏大多数问题。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM