NetCore RabbitMQ 發佈訂閱模式,消息廣播 RabbitMQ的六種工作模式

十年河東,十年河西,莫欺少年窮

學無止境,精益求精

上篇博客介紹了RabbitMQ的六種工作模式 RabbitMQ的六種工作模式 僅登錄用戶可見

RabbitMQ的簡單模式和Work工作模式請參考:NetCore RabbitMQ 簡介及兔子生產者、消費者 【簡單模式,work工作模式,競爭消費】

本篇博客使用NetCore完成RabbitMQ發佈訂閱模式中的廣播模式

何爲廣播模式?

 publish/subscribe發佈訂閱(共享資源)

在這裏插入圖片描述

  1. X代表交換機rabbitMQ內部組件,erlang 消息產生者是代碼完成,代碼的執行效率不高,消息產生者將消息放入交換機,交換機發布訂閱把消息發送到所有消息隊列中,對應消息隊列的消費者拿到消息進行消費
  2. 相關場景:郵件羣發,羣聊天,廣播(廣告)

上圖中X代表交換機,RabbitMQ中交換機的類型分爲四種,分別爲廣播模式,定向模式,通配符模式,參數匹配模式

ExchangeType.Fanout【廣播模式】 

ExchangeType.Direct【定向模式】 

ExchangeType.Topic【通配符模式】 

ExchangeType.Headers 【參數匹配模式】

廣播模式生產者

廣播模式創建生產者,分爲如下步驟,

1、聲明一個交換機

2、聲明廣播的隊列

3、交換機和隊列進行綁定

4、生產消息

以上步驟用NetCore 實現如下:

using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace RabbitMqProducer
{
    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; //消息最大字節數
            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);
                    //聲明一個交換機
                    string Ename = "ExRabbitMQ";
                    channel.ExchangeDeclare(Ename, ExchangeType.Fanout, false, false, null);
                    //聲明廣播的隊列
                    string Qname_1 = "RabbitMQ_Queue_1";
                    string Qname_2 = "RabbitMQ_Queue_2";
                    channel.QueueDeclare(Qname_1, false, false, false, null);
                    channel.QueueDeclare(Qname_2, false, false, false, null);
                    //交換機 隊列 綁定
                    //queue 隊列名稱
                    //exchange  交換機名稱
                    //routingKey  路由規則  
                    //void QueueBind(string queue, string exchange, string routingKey, IDictionary<string, object> arguments);
                    string routingKey = "EQ"; //路由匹配規則 交換機通過routingKey廣播消息到綁定的隊列
                    channel.QueueBind(Qname_1, Ename, routingKey);
                    channel.QueueBind(Qname_2, Ename, routingKey);
                    //發送消息
                    for(int i = 0; i < 100; i++)
                    {
                        var messages = "I am RabbitMQ"; //傳遞的消息內容
                                                        //exchange 交換機,如果使用默認的交換機,那麼routingKey要和隊列的名稱一致
                                                        //routingKey:路由  
                                                        //basicProperties : 用於基礎屬性設置
                        ///BasicPublish(this IModel model, string exchange, string routingKey, IBasicProperties basicProperties, ReadOnlyMemory<byte> body);
                        channel.BasicPublish(Ename, routingKey, null, Encoding.UTF8.GetBytes(messages+"_"+i)); //生產消息
                    }
                }
            }
            Console.Read();
        }
    }
}

這裏需要說明的是,當發佈訂閱模式爲廣播時,需要定義路由規則routingKey,綁定時,routingKey必須保持一致,RabbitMQ廣播是通過routingKey進行隊列匹配的。

消費者

廣播模式生產者代碼中,我們創建了兩個隊列,因此,我們需要兩個消費者分別消費不同隊列的消息,如下:

消費者1

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($"RabbitMQConsumer_1 收到消息: {message}");
                //確認該消息已被消費
                channel.BasicAck(ea.DeliveryTag, false); Thread.Sleep(100);
            };
            //啓動消費者 
            string Qname = "RabbitMQ_Queue_1";
            channel.BasicConsume(Qname, false, consumer);
            Console.WriteLine("消費者已啓動");
            Console.ReadKey();
            channel.Dispose();
            connection.Close();
        }

         

    }
}

消費者2

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
using System.Threading;

namespace RabbitMQConsumer_2
{
    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($"RabbitMQConsumer_2 收到消息: {message}");
                //確認該消息已被消費
                channel.BasicAck(ea.DeliveryTag, false);
                Thread.Sleep(100);
            };
            //啓動消費者 

            string Qname = "RabbitMQ_Queue_2";
            channel.BasicConsume(Qname, false, consumer);
            Console.WriteLine("消費者已啓動");
            Console.ReadKey();
            channel.Dispose();
            connection.Close();
        }
    }
}

效果如下:

 

 @陳臥龍的伯樂

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章