2017-01-16 20 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应该为每个线程新鲜打开

相关问题