2017-01-16 21 views
0

我們有一個將消息發佈到我們的RabbitMQ服務器的ASP.Net WebAPI 2.0應用程序。在99%的情況下,一切都很好......但是隨機應用終止,出現無理由的System.AccessViolationException。RabbiMQ C#驅動程序導致System.AccessViolationException

如何防止此故障?它可能與我們最近升級到3.6.6 C#驅動程序(在升級之前它工作正常)有關嗎?

事情我已經消除:

  1. IModel用於每個發佈(我知道IModel不是線程 安全)
  2. 呼叫要CreateConnection由每個呼叫,以及(我 知道我可以重新使用連接,但我們目前不)。該連接是AutoClose = true;
  3. 的信道是在使用塊中使用...所以每次

下面是其中它爆炸的樣品堆棧跟蹤它設置:

異常詳細信息

System.AccessViolationException

嘗試讀取或寫保護 內存。這通常表明其他內存已損壞。

在System.Net.UnsafeNclNativeMethods.SafeNetHandlesXPOrLater.GetAddrInfoW(字符串 節點名,絃樂服務名,AddressInfo的&提示,SafeFreeAddrInfo & 手柄) 在System.Net.Dns.TryGetAddrInfo(字符串名稱,AddressInfoHints標誌,IPHostEntry & Hostinfo中) at System.Net.Dns.InternalGetHostByName(String hostName,Boolean includeIPv6) at System.Net.Dns.GetHostAddresses(String hostNameOrAddress) at RabbitMQ.Client.TcpClientAdapter.BeginConnect(String host,Int32 port,AsyncCallback requestCallback,Object狀態) at RabbitMQ.Client.Impl.SocketFrameHandler.Connect (ITcpClient插座,AmqpTcpEndpoint端點的Int32超時) 在RabbitMQ.Client.Impl.SocketFrameHandler..ctor(AmqpTcpEndpoint端點,Func`2的SocketFactory,的Int32 connectionTimeout,的Int32 readTimeout,的Int32 writeTimeout) 在RabbitMQ.Client.Framing.Impl .ProtocolBase.CreateFrameHandler(AmqpTcpEndpoint 終點,Func'2的SocketFactory,的Int32 connectionTimeout,的Int32 readTimeout,的Int32 writeTimeout) 在RabbitMQ.Client.ConnectionFactory.CreateConnection(IList'1終點,字符串clientProvidedName)

而另一

System.Net.UnsafeNclNativeMethods + SafeNetHandlesXPOrLater.GetAddrInfoW(System.String, System.String,System.Net.AddressInfo的ByRef, System.Net.SafeFreeAddrInfo的ByRef) System.Net.Dns.TryGetAddrInfo(System.String, System.Net.AddressInfoHints,System.Net.IPHostEntry ByRef) System.Net.Dns.InternalGetHostByName(System。String,Boolean) System.Net.Dns.GetHostAddresses(System.String) RabbitMQ.Client.TcpClientAdapter.BeginConnect(System.String,Int32,System.AsyncCallback,System.Object) RabbitMQ.Client.Impl.SocketFrameHandler.Connect (RabbitMQ.Client.ITcpClient, RabbitMQ.Client.AmqpTcpEndpoint,Int32)將 RabbitMQ.Client.Impl.SocketFrameHandler..ctor(RabbitMQ.Client.AmqpTcpEndpoint, System.Func'2, 的Int32,的Int32,Int32)將 的RabbitMQ .Client.Framing.Impl.ProtocolBase.CreateFrameHandler(RabbitMQ.Client.AmqpTcpEndpoint, System.Func'2, Int32,Int32,Int32) RabbitMQ.Client.ConnectionFactory.CreateConnection(System.Collections.Generic.IList'1, System.String)

回答

0

我不確定你的錯誤發生的原因我需要看一些你的代碼,但我使用RabbitMQ相當多,併發布我使用類似這樣的類:

(改變了一些零件,因爲他們是不相關的您的具體情況,如加密,壓縮等等。但是,這將是它的基本格式)

using System; 
using System.Text; 
using RabbitMQ.Client; 
using RabbitMQ.Client.Framing; 

namespace Messaging 
{ 
    public class MessageSender : IDisposable 
    { 
     private const string EXCHANGE_NAME = "MY_EXCHANGE"; 

     private readonly ConnectionFactory factory; 
     private readonly IConnection connection; 
     private readonly IModel channel; 

     public MessageSender(string address, string username, string password) 
     { 
      factory = new ConnectionFactory {UserName = username, Password = password, HostName = address}; 

      connection = factory.CreateConnection(); 
      channel = connection.CreateModel(); 

      channel.ExchangeDeclare(EXCHANGE_NAME, "topic"); 
     } 

     public void Send(string payload, string topic) 
     { 
      var prop = new BasicProperties(); 
      var data = Encoding.ASCII.GetBytes(payload); 

      channel.BasicPublish(EXCHANGE_NAME, topic.ToUpper(), prop, data); 
     } 

     public void Dispose() 
     { 
      try 
      { 
       channel.Dispose(); 
       connection.Dispose(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
      } 
     } 
    } 
} 

的想法是讓你發出多個電話或者只有一個,並在你希望的時候處理這​​個班級。用一個使用語句和你的設置來包裝它。

在使用它大約3 - 4年的時間裏,從未遇到過這個問題,因此您可以將其與您的代碼進行對比以找出差異。

+0

感謝您的意見。
我們的實現每次都不會創建一個新的「發件人」類,但我們確實將該通道包裝在一個使用中。
爲了記錄,我的實施工作已經進行了3年,沒有問題......最近剛剛開始失敗。也許這是我剛剛升級到的驅動程序版本中的一個錯誤(3.6.6)

+0

您運行的是什麼版本的RabbitMQ。我們在3.6.4中發現了幾個問題。主要的原因是心臟跳動導致客戶端出現故障,並會中斷連接。 (固定在3.3.6我相信根據補丁說明)根據你的錯誤處理,這可能是它。只有通過Windows事件日誌纔會注意到它,該錯誤列出了源自.NET rabbitmq客戶端的錯誤,並將「heartbeats」作爲問題。 – Kelly

+0

我們的驅動程序是3.6.6 ....不確定服務器,但我可以檢查。 –

0

從RabbitMQ用戶組獲取(部分)解決方案。

詳情點擊這裏:Rabbit MQ Users Group

的基本想法是,IConnection對象應該被共享的,因爲它是沉重的打開和關閉。只有IModel應該爲每個線程新鮮打開

相關問題