RabbiMQ C#驱动程序导致System.AccessViolationException

时间:2017-01-16 15:22:36

标签: c# asp.net-web-api rabbitmq

我们有一个ASP.Net WebAPI 2.0应用程序,它将消息发布到我们的RabbitMQ服务器。在99%的情况下,一切都很好...但随机应用程序终止与System.AccessViolationException没有明显的原因。

如何防止此失败?它可能与我们最近升级到3.6.6 C#驱动程序有关(它在升级之前工作正常吗?)

我已经消除的事情:

  1. 每个发布使用一个新的IModel(我知道IModel不是线程 安全)
  2. 每次通话都会拨打CreateConnection(I 知道我可以重用连接,但我们目前没有)。连接是AutoClose = true;
  3. 频道用于一个使用区块......所以每次都要处理它
  4. 以下是它爆炸的示例堆栈跟踪:

    例外详细信息

      

    System.AccessViolationException

         

    尝试读取或写入受保护的   记忆。这通常表明其他内存已损坏。

         

    at System.Net.UnsafeNclNativeMethods.SafeNetHandlesXPOrLater.GetAddrInfoW(String   nodename,String servicename,AddressInfo&提示,SafeFreeAddrInfo&   处理)   在System.Net.Dns.TryGetAddrInfo(String name,AddressInfoHints flags,IPHostEntry& hostinfo)   在System.Net.Dns.InternalGetHostByName(String hostName,Boolean includeIPv6)   在System.Net.Dns.GetHostAddresses(String hostNameOrAddress)   在RabbitMQ.Client.TcpClientAdapter.BeginConnect(String host,Int32 port,AsyncCallback requestCallback,Object state)   在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)   endpoint,Func 2 socketFactory,Int32 connectionTimeout,Int32   readTimeout,Int32 writeTimeout)   在RabbitMQ.Client.ConnectionFactory.CreateConnection(IList' 1端点,String 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)

2 个答案:

答案 0 :(得分: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);
            }
        }
    }
}

这个想法是让你发出多个电话或一个电话,并在你希望的时候处理这​​个课程。用using语句和你的集合包装它。

在使用它的大约3 - 4年内从来没有遇到任何问题,因此您可以将此与您的代码进行对比以找出差异。

答案 1 :(得分:0)

管理从RabbitMQ用户组获得(部分)解决方案。

详细信息:Rabbit MQ Users Group

基本思想是IConnection对象应该被共享,因为它很难打开和关闭。每个线程只应打开新的IModel