1. 程式人生 > >RabbitMQ.Client.TopologyRecoveryException問題與解決

RabbitMQ.Client.TopologyRecoveryException問題與解決

封裝了一下RabbitMQ驅動的呼叫,扔給團隊用,一直也沒出現啥問題,
昨天同事突然反饋給我,說除錯時一直報錯:

Topology recovery exception: RabbitMQ.Client.TopologyRecoveryException: Caught an exception while recovering exchange xxxxx: Already closed: The AMQP operation was interrupted: AMQP close-reason, initiated by Application, code=200, text="Goodbye"
, classId=0, methodId=0, cause= ---> RabbitMQ.Client.Exceptions.AlreadyClosedException: Already closed: The AMQP operation was interrupted: AMQP close-reason, initiated by Application, code=200, text="Goodbye", classId=0, methodId=0, cause= 在 RabbitMQ.Client.Impl.SessionBase.Transmit(Command cmd) 在 RabbitMQ.Client
.Impl.ModelBase.ModelRpc(MethodBase method, ContentHeaderBase header, Byte[] body) 在 RabbitMQ.Client.Framing.Impl.Model._Private_ExchangeDeclare(String exchange, String type, Boolean passive, Boolean durable, Boolean autoDelete, Boolean internal, Boolean nowait, IDictionary`2 arguments) 在 RabbitMQ.Client
.Impl.ModelBase.ExchangeDeclare(String exchange, String type, Boolean durable, Boolean autoDelete, IDictionary`2 arguments) 在 RabbitMQ.Client.Impl.RecordedExchange.Recover() 在 RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.RecoverExchanges()

過去他的機器一看,在除錯過程中,不定時丟擲上面的錯誤,而同樣的程式,線上執行好好的,根本不報錯。
錯誤也說是正常斷開,GoodBye……

找了半天資料,沒發現什麼特別的地方,自己測試發現等一定時間後也會出這個錯誤。
建立連線的程式碼如下:

{
    HostName = "127.0.0.1",
    Port = 5672,
    UserName = "admin",
    Password = "123456",
    //Socket read timeout is twice the hearbeat
    RequestedHeartbeat = 1000,
    AutomaticRecoveryEnabled = true,
};
var connection = connectionFactory.CreateConnection("exchangeName");
return connection;

後面另一個同事看了下,說心跳為啥設定那麼短???
一語驚醒,正常程式碼執行中,心跳機制不會卡住,所以也就不會出錯,
而如果在除錯過程中,加入了斷點,一個斷點等幾秒是很正常的,自然也會卡住心跳機制的正常運作。
參考官方說明:
https://www.rabbitmq.com/heartbeats.html
簡要翻譯下,RabbitMQ的預設心跳時長為60秒,每半個週期(30秒)會發一次心跳包,如果丟失2個心跳包,就會認為連線斷了,需要重新連線。
根據歷年使用者的反饋意見,這個值如果低於5秒,會導致誤報,1秒以下幾乎都會導致誤報,比較合適的值是5~20秒。
設定為0可以禁用心跳機制。

注:設定了RequestedHeartbeat,會同時開啟服務端和客戶端的心跳機制,在指定時間內:
1、服務端在無資料傳送的情況下,會發心跳包給客戶端;或者沒收到客戶端資料,會認為心跳超時;
2、客戶端也會觸發傳送和接收心跳包的Timer機制,判斷髮送和接收超時情況