1. 程式人生 > >RabbitMQ (十) 隊列的參數詳解

RabbitMQ (十) 隊列的參數詳解

pen lee from lac rgs alt des seconds this

代碼中,我們通常這樣聲明一個隊列:

                    //聲明隊列
                    channel.QueueDeclare
                    (
                        queue: QueueName, //隊列名稱
                        durable: false, //隊列是否持久化.false:隊列在內存中,服務器掛掉後,隊列就沒了;true:服務器重啟後,隊列將會重新生成.註意:只是隊列持久化,不代表隊列中的消息持久化!!!!
                        exclusive: false
, //隊列是否專屬,專屬的範圍針對的是連接,也就是說,一個連接下面的多個信道是可見的.對於其他連接時不可見的.連接斷開後,該隊列會被刪除.註意,不是信道斷開,是連接斷開.並且,就算設置成了持久化,也會刪除. autoDelete: true, //如果沒有消費者了,是否自動刪除 (感覺自己沒操作對,這個參數一直沒試驗成功) arguments: null //隊列的配置 );

對於第5個參數: arguments ,

它的類型是一個鍵值對集合 :

技術分享圖片

它到底有哪些key呢?

我們可以通過 RabbitMQ 的管理頁面看到:

技術分享圖片

一共10個,鼠標點擊"?",可以看到官方給出的解釋.

Message TTL

官方 : How long a message published to a queue can live before it is discarded (milliseconds). (Sets the "x-message-ttl" argument.)

翻譯 : 一個隊列中的消息,在被丟棄之前能夠存活多少毫秒.( key 為 "x-message-ttl").通俗講就是,隊列中的消息的生存周期,單位毫秒.

測試 :

    internal class
Program { private static void Main(string[] args) { Dictionary<string, object> arguments = new Dictionary<string, object> { { "x-message-ttl", 10000 } }; Producer.Send(arguments); Console.ReadKey(); } } public class Producer { private const string QueueName = "test_queue"; public static void Send(IDictionary<string,object> arguments) { using (IConnection connection = ConnectionHelper.GetConnection()) using (IModel channel = connection.CreateModel()) { channel.QueueDeclare(QueueName, false, false, false, arguments); string msg = "hello world "; channel.BasicPublish("", QueueName, null, Encoding.Default.GetBytes(msg)); Console.WriteLine($"{DateTime.Now} : send {msg}"); } } }

我們從管理頁面該隊列的消息概述中可以看出,這條消息只存活了10秒鐘.

技術分享圖片

為了加以對比,我還另外創建了一個沒有聲明任何參數的隊列:

技術分享圖片

可以看出,測試的這條隊列的特征(Features)一欄中,被打上了"TTL"標簽.

這裏有個非常重要的知識點需要註意!

隊列一旦聲明,參數將無法更改,添加,刪除,也就是說,對上述"test_queue"隊列進行如下操作都會拋出異常:

  • 修改該隊列的 "x-message-ttl" 參數為 "20000" 毫秒 :
    Dictionary<string, object> arguments = new Dictionary<string, object> { { "x-message-ttl", 20000 } };
  • 試圖通過傳入 null 來刪除該隊列的所有已設置的參數 :
    Dictionary<string, object> arguments = null;
  • 試圖添加新的參數 :
                Dictionary<string, object> arguments = new Dictionary<string, object> { { "x-message-ttl", 10000 } };
                arguments.Add("x-expires", 12345);

通通不行!!!

要改變一個隊列的參數,只有兩種辦法:

  • 刪除該隊列,重新創建;
  • 換個名字,創建一個新的隊列.

Auto expire

官方 : How long a queue can be unused for before it is automatically deleted (milliseconds).(Sets the "x-expires" argument.)

翻譯 : 隊列多長時間(毫秒)沒有被使用(訪問)就會被刪除.換個說法就是,當隊列在指定的時間內沒有被使用(訪問)就會被刪除.

測試 :

        private static void Main(string[] args)
        {
            Dictionary<string, object> arguments = new Dictionary<string, object>
            {
                {"x-message-ttl", 10000},//設置隊列中的消息存活期為 10 秒
                { "x-expires", 20000}//設置隊列的存活期 20 秒
            };
            Producer.Send(arguments);
            Console.ReadKey();
        }

可以看到,隊列特征一欄中,多了一個"Exp"標簽

技術分享圖片

當然,10秒後,消息會被刪除,20秒後,隊列被刪除

但是,如果我們同時創建一個消費者,監聽該隊列,如下:

    public class Consumer
    {
        private const string QueueName = "test_queue";
        public static void Receive()
        {
            IConnection connection = ConnectionHelper.GetConnection();
            IModel channel = connection.CreateModel();
            EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
            consumer.Received += (s, e) =>
            {
                byte[] bytes = e.Body;
                string str = Encoding.Default.GetString(bytes);
                Console.WriteLine("consumer receive : " + str);
            };
            channel.BasicConsume(QueueName, true, "", false, false, null, consumer);
        }
    }

        private static void Main(string[] args)
        {
            Dictionary<string, object> arguments = new Dictionary<string, object>
            {
                {"x-message-ttl", 10000},//設置隊列中的消息存活期為 10 秒
                { "x-expires", 20000}//設置隊列的存活期 20 秒
            };
            Producer.Send(arguments);
            Consumer.Receive();//創建一個消費者監聽該隊列
            Console.ReadKey();
        }

那該隊列永遠不會被刪除.因為雖然它裏面沒有消息,但一直有消費者在使用(訪問)它,所以它不會被刪除.

Max length

官方 : How many (ready) messages a queue can contain before it starts to drop them from its head.(Sets the "x-max-length" argument.)

翻譯 : 隊列可以容納的消息的最大條數,超過這個條數,隊列頭部的消息將會被丟棄.

測試 : 我們設置隊列最多只能容納 1 條消息,然後一次性發送10條,發送完畢後,創建一個消費者去消費,部分代碼如下:

生產者

                for (int i = 0; i < 10; i++)
                {
                    string msg = "hello world " + i;
                    channel.BasicPublish("", QueueName, null, Encoding.Default.GetBytes(msg));
                    Console.WriteLine($"{DateTime.Now} : send {msg}");
                }

        private static void Main(string[] args)
        {
            Dictionary<string, object> arguments = new Dictionary<string, object>
            {
                {"x-message-ttl", 10000},//設置隊列中的消息存活期為 10 秒
                { "x-expires", 20000},//設置隊列的存活期 20 秒
                {"x-max-length",1 },//設置隊列中的消息的最大條數為 1 條,超過1條,則遵循隊列的"先進先出(丟)"原則.
            };
            Producer.Send(arguments);
            Thread.Sleep(1000);
            Consumer.Receive();//創建一個消費者監聽該隊列
            Console.ReadKey();
        }

運行結果:

技術分享圖片

可以看到,消費者消費到的是"hello world 9", "hello world 0" - "hello world 8"都被隊列丟棄了.