RabbitMQ.NET In Window Service

工做中要求使用RabbitMQ,以Windows Service 模式啓動,中間有遇到一些問題,網上大部分博客有誤導傾向, 在這裏作一個簡單的記錄,以避免後面的人走坑;css

1.html

自動從新鏈接,不須要手動處理自動鏈接   測試

AutomaticRecoveryEnabled = true //斷開自動從新鏈接spa

2.由於是Windows Service  ,與控制檯程序不一樣,如果像Demo中直接使用Received ,那麼可能只會接收一次消息,而後程序執行完畢退出操作系統

後來我就使用了While(true),當時測試能解決問題,後來發現運行久了沒有消息接收會時不時的斷開鏈接,出現錯誤消息提示:code

【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測試時正常的,htm

這個錯誤很容易被忽略,應該感受本身Debug沒有問題,怎麼到客戶那裏Windows Service就出錯了,會覺得是安裝包或者是客戶電腦的問題,後來發現是由於While(true)的問題;blog

網上這個問題的不少答案都是說是確認消息 自動確認又手動確認,反正不少,後來發現是沒有用事件的緣由;隊列

在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();

這樣纔不會直接消失;

相關文章
相關標籤/搜索