.net/c# RabbitMQ 鏈接斷開處理-斷線重連(轉載)

Rabbitmq 官方給的NET consumer示例代碼以下,但使用過程,會遇到connection斷開的問題,一旦斷開,這個代碼就會報錯,就會致使消費者或者生產者掛掉。

下圖是生產者發送消息,我手動中止了rabbitmq,而後又從新啓動了rabbitmq,大概等啓動成功之後,爲了防止服務沒有徹底啓動,我又等待了10秒鐘

服務徹底啓動成功之後,我嘗試從新發送一些消息,報錯,以下:
html

************** 異常文本 **************
RabbitMQ.Client.Exceptions.AlreadyClosedException: Already closed: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=320, text="CONNECTION_FORCED - broker forced connection closure with reason 'shutdown'", classId=0, methodId=0, cause=
   在 RabbitMQ.Client.Impl.SessionBase.Transmit(Command cmd)
   在 RabbitMQ.Client.Impl.ModelBase.ModelSend(MethodBase method, ContentHeaderBase header, Byte[] body)
   在 RabbitMQ.Client.Impl.ModelBase.BasicPublish(String exchange, String routingKey, Boolean mandatory, IBasicProperties basicProperties, Byte[] body)
   在 RabbitMQ.Client.Impl.ModelBase.BasicPublish(String exchange, String routingKey, IBasicProperties basicProperties, Byte[] body)
   在 rabbitMQ_Publish.Form1.button1_Click(Object sender, EventArgs e) 位置 C:\project\my\RabbitMQ-demo\rabbitMQ-Publish\Form1.cs:行號 37
   在 System.Windows.Forms.Control.OnClick(EventArgs e)
   在 System.Windows.Forms.Button.OnClick(EventArgs e)
   在 System.Windows.Forms.Button.PerformClick()
   在 System.Windows.Forms.Form.ProcessDialogKey(Keys keyData)
   在 System.Windows.Forms.TextBoxBase.ProcessDialogKey(Keys keyData)
   在 System.Windows.Forms.Control.PreProcessMessage(Message& msg)
   在 System.Windows.Forms.Control.PreProcessControlMessageInternal(Control target, Message& msg)
   在 System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(MSG& msg)






那麼如何會異常恢復呢?或者說斷線重連呢?

RabbitMQ NET Client的源碼,研究發現一種自動的錯誤恢復機制 AutomaticRecoveryEnabled = true 使用方式以下

ide

  1. var factory = new ConnectionFactory() { HostName = "localhost", AutomaticRecoveryEnabled = true };
複製代碼

具體的恢復機制以下

1.在AutoRecoveringConnection初始化時,在連接關閉事件委託上增長斷開處理

this

  1. public void init()
  2.         {
  3.             m_delegate = new Connection(m_factory, false, m_factory.CreateFrameHandler());

  4.             AutorecoveringConnection self = this;
  5.             EventHandler<ShutdownEventArgs> recoveryListener = (_, args) =>
  6.             {
  7.                 lock (recoveryLockTarget)
  8.                 {
  9.                     if (ShouldTriggerConnectionRecovery(args))
  10.                     {
  11.                         try
  12.                         {
  13.                             self.BeginAutomaticRecovery();
  14.                         }
  15.                         catch (Exception e)
  16.                         {
  17.                             // TODO: logging
  18.                             Console.WriteLine("BeginAutomaticRecovery() failed: {0}", e);
  19.                         }
  20.                     }
  21.                 }
  22.             };
  23.             lock (m_eventLock)
  24.             {
  25.                 ConnectionShutdown += recoveryListener;
  26.                 if (!m_recordedShutdownEventHandlers.Contains(recoveryListener))
  27.                 {
  28.                     m_recordedShutdownEventHandlers.Add(recoveryListener);
  29.                 }
  30.             }
  31.         }
複製代碼

觀察調用的方式BeginAutomaticRecovery,能夠看到這個方法內部調用了PerformAutomaticRecovery方法。咱們直接看這個方法的內容,其中第一個調用的是方法RecoverConnectionDelegate
spa

  1. protected void PerformAutomaticRecovery()
  2.         {
  3.             lock (recoveryLockTarget)
  4.             {
  5.                 RecoverConnectionDelegate();
  6.                 RecoverConnectionShutdownHandlers();
  7.                 RecoverConnectionBlockedHandlers();
  8.                 RecoverConnectionUnblockedHandlers();

  9.                 RecoverModels();
  10.                 if (m_factory.TopologyRecoveryEnabled)
  11.                 {
  12.                     RecoverEntities();
  13.                     RecoverConsumers();
  14.                 }

  15.                 RunRecoveryEventHandlers();
  16.             }
  17.         }
複製代碼



這個方法中調用的是
code

  1. protected void RecoverConnectionDelegate()
  2.         {
  3.             bool recovering = true;
  4.             while (recovering)
  5.             {
  6.                 try
  7.                 {
  8.                     m_delegate = new Connection(m_factory, false, m_factory.CreateFrameHandler());
  9.                     recovering = false;
  10.                 }
  11.                 catch (Exception)
  12.                 {
  13.                     // TODO: exponential back-off
  14.                     Thread.Sleep(m_factory.NetworkRecoveryInterval);
  15.                     // TODO: provide a way to handle these exceptions
  16.                 }
  17.             }
  18.         }
複製代碼

能夠看出,它是執行了死循環,直到鏈接從新打開,固然,若是遇到異常,它會調用Thread.Sleep來等待一下,而後再次執行鏈接恢復。orm

 

轉載自: https://www.itsvse.com/thread-4636-1-1.htmlhtm

相關文章
相關標籤/搜索