简体   繁体   English

RabbitMQ 在 .CreateModel() 上抛出 TimeOut 异常

[英]RabbitMQ throwing TimeOut exception on .CreateModel()

I've created a Bus application to encapsulate all the subscribe and publish to a RabbitMQ broker.我创建了一个总线应用程序来封装所有订阅和发布到 RabbitMQ 代理。 This bus is then used as a SDK for others projects of mine.然后这条总线被用作我其他项目的 SDK。 After running this projects (whitch is basicaclly for applications comunicating via RabbitMQ messages using my Bus sdk), I realized that the Bus was throwing a exception a TimeOut exception on the native method .CreateModel(), as follows:在运行这个项目后(对于使用我的 Bus sdk 通过 RabbitMQ 消息进行通信的应用程序来说,这是基本的),我意识到总线在本地方法 .CreateModel() 上抛出了一个 TimeOut 异常,如下所示:

System.TimeoutException: The operation has timed out.
   at RabbitMQ.Util.BlockingCell.GetValue(TimeSpan timeout)
   at RabbitMQ.Client.Impl.SimpleBlockingRpcContinuation.GetReply(TimeSpan timeout)
   at RabbitMQ.Client.Impl.ModelBase.ModelRpc(MethodBase method, ContentHeaderBase header, Byte[] body)
   at RabbitMQ.Client.Framing.Impl.Model._Private_ChannelOpen(String outOfBand)
   at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.CreateNonRecoveringModel()
   at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.CreateModel()

Here are some information about the my RabbitMQ broker: Version: 3.7.2 Erlang: 20.1 OS: Linux Ubuntu (AWS)以下是有关我的 RabbitMQ 代理的一些信息: 版本:3.7.2 Erlang:20.1 操作系统:Linux Ubuntu (AWS)

Here is my RabbitMQConnection class:这是我的 RabbitMQConnection 类:

internal class RabbitMQConnection : IDisposable
{
    private object __syncRoot__ { get; } = new object();

    #region Private
    private bool __disposed__ { get; set; }
    private IConnectionFactory __rmqConnFactory__ { get; }
    private IConnection __rmqConnection__ { get; set; }
    private string __connectionIdentifier__ { get; }
    private ILog __logger__ { get; }
    #endregion

    #region Public
    public bool IsConnected
    {
        get
        {
            DisposeCheck();
            return __rmqConnection__ != null && __rmqConnection__.IsOpen && !__disposed__;
        }
    }

    public int ThreadLimit { get; private set; }

    public IConnection GetConnection
    {
        get
        {
            DisposeCheck();
            if (IsConnected == true)
            {
                return __rmqConnection__;
            }
            else
            {
                return null;
            }
        }
    }

    public bool IsDisposed
    {
        get
        {
            return __disposed__;
        }
    }
    #endregion

    public RabbitMQConnection(RabbitMQConfiguration _rmqConfig)
    {
        __logger__ = LogProvider.GetCurrentClassLogger();

        ConnectionFactory rMQconnFactory = new ConnectionFactory()
        {
            HostName = _rmqConfig.Hostname,
            UserName = _rmqConfig.Username,
            Password = _rmqConfig.Password,
            VirtualHost = _rmqConfig.VirtualHost,
            AutomaticRecoveryEnabled = true,
            DispatchConsumersAsync = true,
        };

        __rmqConnFactory__ = rMQconnFactory;

        ThreadLimit = _rmqConfig.ThreadLimit;

        __connectionIdentifier__ = $"{_rmqConfig.CurrentMachineIPAddress} - {_rmqConfig.CurrentMachineHostname}";

        Connect();

        __disposed__ = false;
    }

    private void Connect()
    {
        DisposeCheck();

        if (__rmqConnection__ == null)
        {
            lock (__syncRoot__)
            {
                if (__rmqConnection__ == null)
                {
                    __rmqConnection__ = __rmqConnFactory__.CreateConnection(__connectionIdentifier__);
                }
            }
        }
    }

    public IModel CreateChannel()
    {

        DisposeCheck();

        if (!IsConnected)
        {
            throw new InvalidOperationException("No RabbitMQ connections are available to perform this action");
        }

        return __rmqConnection__.CreateModel(); // Here is where the exception occurs!!!
    }

    #region ShutdownEvents
    private void OnConnectionBlocked(object sender, ConnectionBlockedEventArgs e)
    {
        if (__disposed__) return;

        //Logar algo
        __logger__.Warn("A RabbitMQ connection (OnConnectionBlocked) is shutdown. Trying to re-connect...");
    }

    void OnCallbackException(object sender, CallbackExceptionEventArgs e)
    {
        if (__disposed__) return;

        //Logar algo
        __logger__.Warn(e?.Exception, "A RabbitMQ connection (OnCallbackException) is shutdown. Trying to re-connect...");
    }

    void OnConnectionShutdown(object sender, ShutdownEventArgs reason)
    {
        if (__disposed__) return;

        //Logar algo
        __logger__.Warn("A RabbitMQ connection (OnConnectionShutdown) is on shutdown. Trying to re-connect...");
    }
    #endregion

    public void Dispose()
    {
        if (__disposed__ == true)
        {
            return;
        }

        try
        {
            __rmqConnection__?.Dispose();
        }
        catch (Exception ex)
        {
            //Log here
            __logger__.Fatal(ex, "RabbitMQ Connection: {0}", ex.Message);
        }
        finally
        {
            __disposed__ = true;
        }
    }

    private void DisposeCheck()
    {
        if (__disposed__ == true)
        {
            throw new ObjectDisposedException("RabbitMQConnection");
        }
    }
}

The exception occurs in the line:异常发生在以下行中:

return __rmqConnection__.CreateModel();

Does anyone has any ideia of why that happens?有没有人知道为什么会这样? I know that sometimes the RabbitMQ connection may oscillate, but I've heard that the RabbitMQ has a native retry to when that happens.我知道有时 RabbitMQ 连接可能会发生振荡,但我听说 RabbitMQ 会在发生这种情况时进行本地重试。

I don't know how much relevant its now.我不知道它现在有多大关系。 Exception is {System.TimeoutException} The operation has timed out.异常为 {System.TimeoutException} 操作已超时。 If we remove AutomaticRecoveryEnabled = true in connection factory, not generating exception and channel is created.如果我们在连接工厂中删除AutomaticRecoveryEnabled = true ,则不会生成异常并创建通道。

For what it's worth;物有所值; I've had this error when there were too many channels already created on the IConnection .IConnection上已经创建了太多频道时,我遇到了这个错误。 The error didn't indicate this unfortunately, but scaling down the number of channels stopped the error from happening.不幸的是,错误并没有表明这一点,但是减少通道数量阻止了错误的发生。

The max number of channels can be set both in the client and server .可以在客户端和服务器中设置最大通道数。

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

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