RabbitMQ.NET In Window Service
工作中要求使用RabbitMQ,以Windows Service 模式启动,中间有遇到一些问题,网上大部分博客有误导倾向, 在这里做一个简单的记录,以免后面的人走坑;
1.
自动重新连接,不需要手动处理自动连接
AutomaticRecoveryEnabled = true //断开自动重新连接
2.因为是Windows Service ,与控制台程序不同,若是像Demo中直接使用Received ,那么可能只会接收一次消息,然后程序执行完毕退出
后来我就使用了While(true),当时测试能解决问题,后来发现运行久了没有消息接收会时不时的断开连接,出现错误消息提示:
【ErrorType】System.IO.EndOfStreamException 【TargetSite】T Dequeue() 【Message】SharedQueue closed 【Source】RabbitMQ.Client 【StackTrace】 at RabbitMQ.Util.SharedQueue`1.Dequeue() at ******
开始以为是RabbitMQ.Net的版本问题,观察对比了几次发现并不是这个问题,高版本的程序也存在这个问题,低版本的也有,而且只有在Windows Service中才会有这个错误,直接Debug测试时正常的,
这个错误很容易被忽略,应该感觉自己Debug没有问题,怎么到客户那里Windows Service就出错了,会以为是安装包或者是客户电脑的问题,后来发现是因为While(true)的问题;
网上这个问题的很多答案都是说是确认消息 自动确认又手动确认,反正很多,后来发现是没有用事件的原因;
在http://www.cnblogs.com/maanshancss/p/7905976.html 也提到了不用while(true),我开始还以为只是异常处理部分作者没有处理呢,实际上需要另外一种写法,针对的Window Service 的,文章后面会贴出来源码;
3.需要理解XP和Win7 etc. 不同操作系统中 Window Service 账户的区别
4.参考http://www.cnblogs.com/maanshancss/p/7905976.html
中的内容,有些是需要注意的
try { string amqEndpoint = System.Configuration.ConfigurationManager.AppSettings["MQEndpoint"].ToString(); string amqUsername = System.Configuration.ConfigurationManager.AppSettings["MQUserName"].ToString(); string amqPassword = System.Configuration.ConfigurationManager.AppSettings["MQPassword"].ToString(); var amqName = System.Configuration.ConfigurationManager.AppSettings["MQName"].ToString(); var exchangeType = "direct"; var uri = new Uri("amqp://" + amqEndpoint + "/"); var factory = new ConnectionFactory { UserName = amqUsername, Password = amqPassword, RequestedHeartbeat = 60, Endpoint = new AmqpTcpEndpoint(uri), AutomaticRecoveryEnabled = true //断开自动重新连接 }; var connection = factory.CreateConnection(); var channel = connection.CreateModel(); channel.QueueDeclare(queue: amqName, durable: true, exclusive: false, autoDelete: false, arguments: null); //创建基于该队列的消费者,绑定事件 var consumer = new EventingBasicConsumer(channel); //绑定消费者 channel.BasicConsume(queue: amqName, //队列名 noAck: false, //false:手动应答;true:自动应答 consumer: consumer); consumer.Received += (model, ea) => { try { //TOOD 验证程序退出后消费者是否退出去了 var body = ea.Body; //消息主体 var message = Encoding.UTF8.GetString(body); Logger.WriteAndShowLog(message); // Method(message); channel.BasicAck(ea.DeliveryTag, false); } catch (RabbitMQ.Client.Exceptions.OperationInterruptedException ex1) { Logger.CreateErrorLog(ex1, "OperationInterruptedException"); Thread.Sleep(5000); channel.BasicNack(ea.DeliveryTag, false, true); } catch (Exception ex) { Logger.CreateErrorLog(ex, "Exception"); Thread.Sleep(5000); channel.BasicNack(ea.DeliveryTag, false, true); } }; Console.ReadLine(); } catch (System.Exception ex) { Logger.CreateErrorLog(ex); Console.ReadLine(); }
与Demo不同的地方
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
这样才不会直接消失;
出处:http://www.cnblogs.com/maanshancss/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。所有源码遵循Apache协议,使用必须添加 from maanshancss