2017-01-16 4 views
0

У нас есть приложение ASP.Net WebAPI 2.0, которое публикует сообщения на нашем сервере RabbitMQ. В 99% случаев все хорошо ... но случайным образом приложение прекращается с исключением System.AccessViolationException без видимых причин.RabbiMQ C# драйвер вызывает System.AccessViolationException

Как предотвратить эту ошибку? Может быть, это связано с недавним обновлением драйвера 3.6.6 C# (он отлично работал до обновления)?

Вещи, которые я уже устранен:

  1. Новый IModel используется для каждой опубликовывать (я знаю IModel не нитку сейф)
  2. Вызов производится в CreateConnection для каждого вызова, а (I знаю, что я могу повторно использовать соединение, но сейчас мы этого не делаем). Соединение AutoClose = true;
  3. Канал используется в блоке, используя ... так он расположен каждый раз, когда

Вот стопка образца след, где она взрывается:

Сведения об исключении

System.AccessViolationException

Попытка чтения или защищен от записи память. Это часто свидетельствует о том, что другая память повреждена.

в System.Net.UnsafeNclNativeMethods.SafeNetHandlesXPOrLater.GetAddrInfoW (String NODENAME, String SERVICENAME, AddressInfo & намеков, SafeFreeAddrInfo & ручка) на System.Net.Dns.TryGetAddrInfo (имя String, AddressInfoHints флаги, IPHostEntry & hostinfo) в System.Net.Dns.InternalGetHostByName (String, Boolean HostName includeIPv6) в System.Net.Dns.GetHostAddresses (Строка hostNameOrAddress) в RabbitMQ.Client.TcpClientAdapter.BeginConnect (String хост, порт Int32, AsyncCallback requestCallback, Object состояние) у 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 конечных точек, 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)

ответ

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 должен быть открыт для каждой нитки

Смежные вопросы