簡體   English   中英

Rabbit MQ - 連接/通道/消費者的恢復

[英]Rabbit MQ - Recovery of connection/channel/consumer

我正在創建一個以無限循環運行的使用者,以從隊列中讀取消息。 我正在尋找有關如何在無限循環中恢復 abd continue 的建議/示例代碼,即使出現網絡中斷也是如此。 消費者必須保持運行,因為它將作為 WindowsService 安裝。

1)有人可以解釋如何正確使用這些設置嗎? 它們之間有什么區別?

NetworkRecoveryInterval 
AutomaticRecoveryEnabled
RequestedHeartbeat

2)請查看我當前的消費者示例代碼。 我正在使用 .Net RabbitMQ Client v3.5.6。

以上設置將如何為我“恢復”? 例如,consumer.Queue.Dequeue 會阻塞直到它被恢復嗎? 好像不太對,所以...

我必須手動編碼嗎? 例如,consumer.Queue.Dequeue 會拋出一個異常,我必須檢測並手動重新創建我的連接、通道和消費者嗎? 或者只是消費者,因為“AutomaticRecovery”會為我恢復頻道?

這是否意味着我應該將消費者創建移動到 while 循環中? 頻道創建呢? 和連接創建?

3) 假設我必須手動執行一些恢復代碼,是否有事件回調(以及如何注冊它們)告訴我存在網絡問題?

謝謝!

public void StartConsumer(string queue)
{
            using (IModel channel = this.Connection.CreateModel())
            {
                var consumer = new QueueingBasicConsumer(channel);
                const bool noAck = false;
                channel.BasicConsume(queue, noAck, consumer);

                // do I need these conditions? or should I just do while(true)???
                while (channel.IsOpen &&        
                       Connection.IsOpen &&     
                       consumer.IsRunning)
                {
                    try
                    {
                        BasicDeliverEventArgs item;
                        if (consumer.Queue.Dequeue(Timeout, out item))
                        {
                            string message = System.Text.Encoding.UTF8.GetString(item.Body);
                            DoSomethingMethod(message);
                            channel.BasicAck(item.DeliveryTag, false);
                        }
                    }
                    catch (EndOfStreamException ex)
                    {   
                        // this is likely due to some connection issue -- what am I to do?
                    }
                    catch (Exception ex)
                    {   
                        // should never happen, but lets say my DoSomethingMethod(message); throws an exception
                        // presumably, I'll just log the error and keep on going
                    }
                }
            }
}

        public IConnection Connection
        {
            get
            {
                if (_connection == null) // _connection defined in class -- private static IConnection _connection;
                {
                     _connection = CreateConnection();
                }
                return _connection;
            }
        }

        private IConnection CreateConnection()
        {
            ConnectionFactory factory = new ConnectionFactory()
            {
                HostName = "RabbitMqHostName",
                UserName = "RabbitMqUserName",
                Password = "RabbitMqPassword",
            };

            // why do we need to set this explicitly? shouldn't this be the default?
            factory.AutomaticRecoveryEnabled = true;

            // what is a good value to use?
            factory.NetworkRecoveryInterval = TimeSpan.FromSeconds(5); 

            // what is a good value to use? How is this different from NetworkRecoveryInterval?
            factory.RequestedHeartbeat = 5; 

            IConnection connection = factory.CreateConnection();
            return connection;
        }

RabbitMQ 特性

RabbitMQ 網站上文檔實際上非常好。 如果您想恢復隊列、交換器和消費者,您正在尋找默認啟用的拓撲恢復 自動恢復( 默認啟用)包括:

  • 重新連接
  • 恢復連接偵聽器
  • 重新開放渠道
  • 恢復頻道偵聽器
  • 恢復通道basic.qos設置、發布者確認和交易設置

NetworkRecoveryInterval是執行自動恢復重試之前的時間量(默認為 5 秒)。

Heartbeat 還有一個目的,即識別死 TCP 連接。 在 RabbitMQ 的站點上可以閱讀更多相關內容

代碼示例

編寫可靠的恢復代碼很棘手。 EndOfStreamException是(如您所懷疑的)最有可能是由於網絡問題。 如果您使用管理插件,您可以通過從那里關閉連接來重現這一點,並查看是否觸發了異常。 對於類似生產的應用程序,您可能希望擁有一組代理,以便在連接失敗時交替使用。 如果您有多個 RabbitMQ 代理,您可能還想保護自己免受一台或多台服務器上的長期服務器故障的影響。 您可能想要實施錯誤策略,例如將消息重新排隊,或使用死信交換。

我一直在思考這些事情,並編寫了一個瘦客戶端RawRabbit來處理其中的一些事情。 也許它可能對你有用? 如果沒有,我建議您將QueueingBasicConsumer更改為EventingBasicConsumer 它是事件驅動的,而不是線程阻塞。

var eventConsumer = new EventingBasicConsumer(channel);
eventConsumer.Received += (sender, args) =>
{
    var body = args.Body;
    eventConsumer.Model.BasicAck(args.DeliveryTag, false);
};
channel.BasicConsume(queue, false, eventConsumer);

如果您激活了拓撲恢復,則消費者將被 RabbitMQ 客戶端恢復並重新開始接收消息。 對於更精細的控制,為ConsumerCancelledShutdown連接事件處理程序以檢測連接問題並Registered以了解何時可以再次使用消費者。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM