十年河東,十年河西,莫欺少年窮
學無止境,精益求精
上篇博客介紹了RabbitMQ的六種工作模式 RabbitMQ的六種工作模式
RabbitMQ的簡單模式和Work工作模式請參考:NetCore RabbitMQ 簡介及兔子生產者、消費者 【簡單模式,work工作模式,競爭消費】
RabbitMQ發佈訂閱模式之消息廣播請參考:NetCore RabbitMQ 發佈訂閱模式,消息廣播
本篇博客使用NetCore完成RabbitMQ發佈訂閱模式中的定向模式
何爲定向模式?
1.4 routing路由模式
- 消息生產者將消息發送給交換機按照路由判斷,路由是字符串(info) 當前產生的消息攜帶路由字符(對象的方法),交換機根據路由的key,只能匹配上路由key對應的消息隊列,對應的消費者才能消費消息;
- 根據業務功能定義路由字符串
- 從系統的代碼邏輯中獲取對應的功能字符串,將消息任務扔到對應的隊列中業務場景:error 通知;EXCEPTION;錯誤通知的功能;傳統意義的錯誤通知;客戶通知;利用key路由,可以將程序中的錯誤封裝成消息傳入到消息隊列中,開發者可以自定義消費者,實時接收錯誤;
上圖中X代表交換機,RabbitMQ中交換機的類型分爲四種,分別爲廣播模式,定向模式,通配符模式,參數匹配模式
ExchangeType.Fanout【廣播模式】
ExchangeType.Direct【定向模式】
ExchangeType.Topic【通配符模式】
ExchangeType.Headers 【參數匹配模式】
廣播模式中,我們通過設定相同的RoutingKey,完成消息的廣播,定向模式中,我們只需在隊列綁定交換機時賦值不同的RoutingKey且生產者生產消息時指定響應的RoutingKey即可完成消息定向到對應隊列。
定向模式生產者
定向模式創建生產者,分爲如下步驟,
1、聲明一個交換機
2、聲明廣播的隊列
3、交換機和隊列進行綁定【創建不同的routingKey,用於區分綁定規則】
4、生產消息,生產消息時,指定生產消息的routingKey,已達到消息定向的作用
以上步驟用NetCore 實現如下:
using RabbitMQ.Client; using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace RabbitMqProducer { class Program { /// <summary> /// 本示例紅色預警爲最高預警級別,藍色預警次之,黃色預警等級最差 /// 紅色預警隊列中只展示紅色預警消息, /// 藍色預警隊列中展示紅色預警和藍色預警 /// 黃色預警隊列展示紅、藍、黃三種預警 /// </summary> /// <param name="args"></param> static void Main(string[] args) { ConnectionFactory factory = new ConnectionFactory(); factory.HostName = "127.0.0.1"; //主機名 factory.UserName = "guest";//使用的用戶 factory.Password = "guest";//用戶密碼 factory.Port = 5672;//端口號 factory.VirtualHost = "/"; //虛擬主機 factory.MaxMessageSize = 1024; //消息最大字節數 using (var connection = factory.CreateConnection()) { //rabbitMQ 基於信道進行通信,因此,我們需要實例化信道Channel using (var channel = connection.CreateModel()) { //exchange 交換機名稱 //type 交換機類型 ExchangeType.Direct【定向模式】 ExchangeType.Fanout【廣播模式】 ExchangeType.Topic【通配符模式】 ExchangeType.Headers 【參數匹配模式】 //durable 是否持久化 //autoDelete 隊列是否爲臨時隊列 //arguments 其他配置 詳見博客:https://www.cnblogs.com/chenwolong/p/RabbitMQ_S.html //void ExchangeDeclare(string exchange, string type, bool durable, bool autoDelete, IDictionary<string, object> arguments); //聲明一個交換機 類型 : Direct string Ename = "ExRabbitMQ_Direct"; channel.ExchangeDeclare(Ename, ExchangeType.Direct, false, false, null); //聲明廣播的隊列 string Qname_Red = "RabbitMQ_Queue_Red"; string Qname_Blue = "RabbitMQ_Queue_Blue"; string Qname_Yellow = "RabbitMQ_Queue_Yellow"; channel.QueueDeclare(Qname_Red, false, false, false, null); channel.QueueDeclare(Qname_Blue, false, false, false, null); channel.QueueDeclare(Qname_Yellow, false, false, false, null); //交換機 隊列 綁定 //queue 隊列名稱 //exchange 交換機名稱 //routingKey 路由規則 //void QueueBind(string queue, string exchange, string routingKey, IDictionary<string, object> arguments); string routingKey_Red = "Red"; // 紅色預警 string routingKey_Blue = "Blue"; // 藍色預警 string routingKey_Yellow = "Yellow"; // 黃色預警 //只接受紅色預警 channel.QueueBind(Qname_Red, Ename, routingKey_Red); // Qname_Blue接受兩種消息類型 channel.QueueBind(Qname_Blue, Ename, routingKey_Red); channel.QueueBind(Qname_Blue, Ename, routingKey_Blue); // Qname_Yellow 介紹三種消息類型 channel.QueueBind(Qname_Yellow, Ename, routingKey_Red); channel.QueueBind(Qname_Yellow, Ename, routingKey_Blue); channel.QueueBind(Qname_Yellow, Ename, routingKey_Yellow); //發送消息 for(int i = 0; i < 10 ; i++) { var messages_Red = "I am Red Police"; //傳遞的消息內容 var messages_Blue = "I am Blue Police"; //傳遞的消息內容 var messages_Yellow = "I am Yellow Police"; //傳遞的消息內容 //exchange 交換機,如果使用默認的交換機,那麼routingKey要和隊列的名稱一致 //routingKey:路由 //basicProperties : 用於基礎屬性設置 ///BasicPublish(this IModel model, string exchange, string routingKey, IBasicProperties basicProperties, ReadOnlyMemory<byte> body); channel.BasicPublish(Ename, routingKey_Red, null, Encoding.UTF8.GetBytes(messages_Red + "_" + i)); //生產紅色預警消息 channel.BasicPublish(Ename, routingKey_Blue, null, Encoding.UTF8.GetBytes(messages_Blue + "_" + i)); //生產藍色預警消息 channel.BasicPublish(Ename, routingKey_Yellow, null, Encoding.UTF8.GetBytes(messages_Yellow + "_" + i)); //生產黃色預警消息 } } } Console.Read(); } } }
執行上述代碼,得到如下信息
此時:三個隊列中紅色預警隊列有10條消息,藍色預警隊列有20條消息,黃色預警隊列有30條消息
交換機信息,注意交換機的類型爲定向模式
定向模式消費者
【紅色預警隊列消費者】
using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace RabbitMqConsumer { class Program { static void Main(string[] args) { ConnectionFactory factory = new ConnectionFactory(); factory.HostName = "127.0.0.1"; //主機名 factory.UserName = "guest";//使用的用戶 factory.Password = "guest";//用戶密碼 factory.Port = 5672;//端口號 factory.VirtualHost = "/"; //虛擬主機 factory.MaxMessageSize = 1024; //消息最大字節數 //創建連接 var connection = factory.CreateConnection(); //創建通道 var channel = connection.CreateModel(); //事件基本消費者 EventingBasicConsumer consumer = new EventingBasicConsumer(channel); //接收到消息事件 consumer.Received += (ch, ea) => { var message = Encoding.UTF8.GetString(ea.Body.ToArray()); Console.WriteLine($"紅色預警隊列消費者收到紅色預警消息: {message}"); //確認該消息已被消費 channel.BasicAck(ea.DeliveryTag, false); Thread.Sleep(100); }; //啓動消費者 string Qname = "RabbitMQ_Queue_Red"; channel.BasicConsume(Qname, false, consumer); Console.WriteLine("消費者已啓動"); Console.ReadKey(); channel.Dispose(); connection.Close(); } } }
因爲紅色預警隊列只綁定了紅色預警的RoutingKey,因此,該隊列只接受紅色預警消息
【藍色預警隊列消費者】
using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace RabbitMqConsumer { class Program { static void Main(string[] args) { ConnectionFactory factory = new ConnectionFactory(); factory.HostName = "127.0.0.1"; //主機名 factory.UserName = "guest";//使用的用戶 factory.Password = "guest";//用戶密碼 factory.Port = 5672;//端口號 factory.VirtualHost = "/"; //虛擬主機 factory.MaxMessageSize = 1024; //消息最大字節數 //創建連接 var connection = factory.CreateConnection(); //創建通道 var channel = connection.CreateModel(); //事件基本消費者 EventingBasicConsumer consumer = new EventingBasicConsumer(channel); //接收到消息事件 consumer.Received += (ch, ea) => { var message = Encoding.UTF8.GetString(ea.Body.ToArray()); Console.WriteLine($"藍色預警隊列消費者收到消息: {message}"); //確認該消息已被消費 channel.BasicAck(ea.DeliveryTag, false); Thread.Sleep(100); }; //啓動消費者 string Qname = "RabbitMQ_Queue_Blue"; channel.BasicConsume(Qname, false, consumer); Console.WriteLine("消費者已啓動"); Console.ReadKey(); channel.Dispose(); connection.Close(); } } }
【黃色預警消費者】
using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace RabbitMqConsumer { class Program { static void Main(string[] args) { ConnectionFactory factory = new ConnectionFactory(); factory.HostName = "127.0.0.1"; //主機名 factory.UserName = "guest";//使用的用戶 factory.Password = "guest";//用戶密碼 factory.Port = 5672;//端口號 factory.VirtualHost = "/"; //虛擬主機 factory.MaxMessageSize = 1024; //消息最大字節數 //創建連接 var connection = factory.CreateConnection(); //創建通道 var channel = connection.CreateModel(); //事件基本消費者 EventingBasicConsumer consumer = new EventingBasicConsumer(channel); //接收到消息事件 consumer.Received += (ch, ea) => { var message = Encoding.UTF8.GetString(ea.Body.ToArray()); Console.WriteLine($"黃色預警隊列消費者收到消息: {message}"); //確認該消息已被消費 channel.BasicAck(ea.DeliveryTag, false); Thread.Sleep(100); }; //啓動消費者 string Qname = "RabbitMQ_Queue_Yellow"; channel.BasicConsume(Qname, false, consumer); Console.WriteLine("消費者已啓動"); Console.ReadKey(); channel.Dispose(); connection.Close(); } } }
定向模式中的核心爲路由Key的聲明、路由Key的綁定、發送帶有路由Key的消息,這3點爲實現定向發送的核心。
@陳大六的博客