體驗Rabbitmq強大的【優先順序隊列】之輕鬆面對現實業務場景

来源:http://www.cnblogs.com/huangxincheng/archive/2016/11/04/6029214.html
-Advertisement-
Play Games

說到隊列的話,大家一定不會陌生,但是扯到優先順序隊列的話,還是有一部分同學是不清楚的,可能是不知道怎麼去實現吧,其實呢,,,這東西已 經爛大街了。。。很簡單,用“堆”去實現的,在我們系統中有一個訂單催付的場景,我們客戶的客戶在tmall,taobao下的訂單,taobao會及時將訂單推送給 我們,如果 ...


         說到隊列的話,大家一定不會陌生,但是扯到優先順序隊列的話,還是有一部分同學是不清楚的,可能是不知道怎麼去實現吧,其實呢,,,這東西已

經爛大街了。。。很簡單,用“堆”去實現的,在我們系統中有一個訂單催付的場景,我們客戶的客戶在tmall,taobao下的訂單,taobao會及時將訂單推送給

我們,如果在用戶設定的時間內未付款那麼就會給用戶推送一條簡訊提醒,很簡單的一個功能對吧,但是,tmall商家對我們來說,肯定是要分大客戶和小客

戶的對吧,比如像施華蔻,百雀林這樣大商家一年起碼能夠給我們貢獻幾百萬,所以理應當然,他們的訂單必須得到優先處理,而曾今我們的後端系統是使

用redis來存放的定時輪詢,大家都知道redis只能用List做一個簡簡單單的消息隊列,並不能實現一個優先順序的場景,所以訂單量大了後採用rabbitmq進行

改造和優化,如果發現是大客戶的訂單給一個相對比較高的優先順序,否則就是預設優先順序,好了,廢話不多說,我們來看看如何去設置。

 

一:優先順序隊列

  既然是優先順序隊列,那麼必然要在Queue上開一個口子貼上一個優先順序的標簽,為了看怎麼設置,我們用一下rabbitmq的監控UI,看看這個裡面是如何

手工的創建優先順序隊列。

      從這個圖中可以看到在Arguments欄中有特別多的小屬性,其中有一項就是"Maximum priority",這項的意思就是說可以定義優先順序的最大值,其實

想想也是,不可能我們定義的優先順序是一個非常大的數字,比如int.MaxValue,大多情況下都是10以內的數字就可以了,再或者我們曾今接觸過的 MSMQ,

它的優先順序只是一些枚舉值,什麼High,Normal,Low,不知道大家可否記得? 下麵來看下代碼中該如何實現呢???

 

1. 在Queue上附加優先順序屬性

Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("x-max-priority", 20);
channel.QueueDeclare(queue: "hello",
                                durable: true,
                                exclusive: false,
                                autoDelete: false,
                                arguments: dic);

 

 上面的代碼做了一個簡單的隊列聲明,queuename="hello",持久化,排外。。。然後把"x-max-priority"塞入到字典中作為arguments參數,看起來還

是非常簡單吧~~~

 

2. 在Message上指定優先順序屬性

 var properties = channel.CreateBasicProperties();
 properties.Priority = 1;
 channel.BasicPublish(exchange: "",
                      routingKey: "hello",
                      basicProperties: null,
                      body: body);

 

通過上面的代碼可以看到,在Message上設置優先順序,我是通過在channel通道上設置Priority屬性,之後塞到basicProperties中就可以了,好了,有上面這兩

個基礎之後,下麵就可以開始測試了,準備向rabbitmq推送10條記錄,其中第5條的優先順序最高,所以應該首先就print出來,如下圖:

static void Main(string[] args)
{
    var sb = new StringBuilder();

    for (int i = 0; i < 11; i++)
    {
        sb.Append(i);
    }

    var factory = new ConnectionFactory() { HostName = "192.168.23.136", UserName = "datamip", Password = "datamip" };

    using (var connection = factory.CreateConnection())
    {
        using (var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(exchange: "mydirect", type: ExchangeType.Direct, durable: true);

            Dictionary<string, object> dic = new Dictionary<string, object>();
            dic.Add("x-max-priority", 20);

            for (int i = 0; i < 10; i++)
            {
                channel.QueueDeclare(queue: "hello",
                                            durable: true,
                                            exclusive: false,
                                            autoDelete: false,
                                            arguments: dic);

                string message = string.Format("{0} {1}", i, sb.ToString());
                var body = Encoding.UTF8.GetBytes(message);

                var properties = channel.CreateBasicProperties();

                properties.Priority = (i == 5) ? (byte)10 : (byte)i;

                channel.BasicPublish(exchange: "",
                                     routingKey: "hello",
                                     basicProperties: properties,
                                     body: body);

                Console.WriteLine(" [x] Sent {0}", i);
            }
        }
    }

    Console.WriteLine(" Press [enter] to exit.");
    Console.ReadLine();
}

 

圖中可以看到10條消息我都送到rabbitmq中去了,接下來打開consume端,來看看所謂的index=5 是否第一個送出來??

static void Main(string[] args)
{
    for (int m = 0; m < int.MaxValue; m++)
    {
        var factory = new ConnectionFactory() { HostName = "192.168.23.136", UserName = "datamip", Password = "datamip" };

        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            var result = channel.BasicGet("hello", true);

            if (result != null)
            {
                var str = Encoding.UTF8.GetString(result.Body);
                Console.WriteLine("{0}  消息內容 {1}", m, str);
                System.Threading.Thread.Sleep(1);
            }
        }
    }
    Console.WriteLine(" Press [enter] to exit.");
    Console.ReadLine();
}

 

一切都是這麼的完美,接下來為了進行可視化驗證,你可以在WebUI中觀察觀察,可以發現在Queue上面多了一個 Pri 標記,有意思吧。

 

 

好了,這麼重要的功能,是不是已經讓你足夠興奮啦, 希望大家能夠好好的在實際場景中運用吧~~~

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • sql server 2012深入解析與性能優化(第3版) 第五章 查詢處理和執行 1.sqlserver通過四個步驟處理一個查詢,分析,algebrizing,優化,執行。2.分析是分析語法錯誤生成分析樹,綁定部分有,名字解析,類型推倒,聚合綁定,組合綁定。查詢優化器,將查詢樹找到好的執行計劃,如 ...
  • 最近學習了一下SQL的分頁查詢,總結了以下幾種方法。 首先建立了一個表,隨意插入的一些測試數據,表結構和數據如下圖: 現在假設我們要做的是每頁5條數據,而現在我們要取第三頁的數據。(數據太少,就每頁5條了) 方法一: 結果: 此方法是先取出前10條的SID(前兩頁),排除前10條數據的SID,然後在 ...
  • 介紹 LIST分區和RANGE分區非常的相似,主要區別在於LIST是枚舉值列表的集合,RANGE是連續的區間值的集合。二者在語法方面非常的相似。同樣建議LIST分區列是非null列,否則插入null值如果枚舉列表裡面不存在null值會插入失敗,這點和其它的分區不一樣,RANGE分區會將其作為最小分區 ...
  • 標簽: MongoDB NoSQL MongoDB 存儲引擎和數據模型設計 1. 存儲引擎 1.1 存儲引擎是什麼 1.2 MongoDB中的預設存儲引擎 2. 數據模型設計 2.1 內嵌和引用 2.2 設計原則 A. 1 1 或者 1 (較少) B. 1 (較多) C. 1 (非常多) D. E. ...
  • 1. 概述 最近在ESB項目中,客戶在各個系統之間的服務調用大多都是在oracle存儲過程中進行的,本文就oracle存儲過程調用web service來進行說明。其他主流資料庫,比如mysql和sql service,調用web service的方法這裡就不做介紹了,本文主要用來介紹oracle存 ...
  • 今天在將CSV導入到oracle時,報了下麵的異常: SQL*Loader-522: lfiopn failed for file 後來從MSDN找到了原因,文件夾的許可權不夠。 環境描述:我的導入文件放在WIN7系統桌面上的,該導入文件是從桌面上另外一個成功導入的例子 複製的 。 處理方案:複製到的 ...
  • 使用ES的基本都會使用過head,但是版本升級到5.0後,head插件就不好使了。下麵就看看如何在5.0中啟動Head插件吧! "官方粗略教程" Running with built in server enable cors by adding http.cors.enabled: true in ...
  • 介紹 COLUMN分區是5.5開始引入的分區功能,只有RANGE COLUMN和LIST COLUMN這兩種分區;支持整形、日期、字元串;RANGE和LIST的分區方式非常的相似。 COLUMNS和RANGE和LIST分區的區別 1.針對日期欄位的分區就不需要再使用函數進行轉換了,例如針對date字 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...