【rabbitMQ】-延遲佇列-模擬控制智慧家居的操作指令

2023-05-26 21:00:23
這個需求為控制智慧家居工作,把控制智慧家居的操作指令發到佇列中,比如:掃地機、洗衣機到指定時間工作
 
一.什麼是延遲佇列?
延遲佇列儲存的物件是對應的延遲訊息,所謂「延遲訊息」 是指當訊息被傳送以後,並不想讓消費者立刻拿到訊息,而是等待特定時間後,消費者才能拿到這個訊息進行消費。

 

二.如何設定延遲佇列?

1.設定2個業務佇列(掃地機執行命令業務佇列,洗衣機執行命令業務佇列),繫結到業務交換機上

2.為業務佇列設定死信交換機和路由key

3.為死信交換機設定2個延遲佇列(掃地機執行命令延遲佇列,洗衣機執行命令延遲佇列)
 

 


 


 

 

三.延遲佇列程式碼落地

 

using MengLin.Shopping.RabbitMQ.Common;
using RabbitMQ.Client;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MengLin.Shopping.RabbitMQ.MsgProducer.QueueType.Delay
{
    /// <summary>
    /// 延遲佇列
    /// </summary>
    public class DelayQueue
    {
        public static void SendMessage()
        {
            //業務交換機
            var exchangeBusiness = "business-exchange";
            
            var queueBusinessSaoDiJiCommand = "SaoDiJiCommand-business-queue";//掃地機執行命令業務佇列
            var routeKeyBusinessSaoDiJiCommand = "SaoDiJiCommand-business-routekey";//掃地機執行命令路由key

            var queueBusinessXiYiJiCommand = "XiYiJiCommand-business-queue";//洗衣機執行命令業務佇列
            var routeKeyBusinessXiYiJiCommand = "XiYiJiCommand-business-routekey";//洗衣機執行命令路由key

            //死信交換機
            var exchangeDeadLetter = "deadLetter-exchange";

            //掃地機執行命令的延時佇列和路由key
            var delaySaoDiJiCommandQueue = "SaoDiJiCommand-delay-queue";
            var routeKeyDelaySaoDiJi = "SaoDiJi-delay-routekey";

            //洗衣機執行命令的延時佇列和路由key
            var delayXiYiJiCommandQueue = "XiYiJiCommand-delay-queue";
            var routeKeyDelayXiYiJi = "XiYiJi-delay-routekey";

            using (var connection = RabbitMQHelper.GetConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    //建立死信交換機(死信交換機對交換機型別沒有要求)
                    channel.ExchangeDeclare(exchange: exchangeDeadLetter, type: ExchangeType.Direct, durable: true, autoDelete: false);

                    //建立掃地機執行命令的延時佇列
                    channel.QueueDeclare(queue: delaySaoDiJiCommandQueue, durable: true, exclusive: false, autoDelete: false);

                    //建立洗衣機執行命令的延時佇列
                    channel.QueueDeclare(queue: delayXiYiJiCommandQueue, durable: true, exclusive: false, autoDelete: false);

                    //繫結死信交換機到掃地機執行命令的延時佇列
                    channel.QueueBind(exchange: exchangeDeadLetter, queue: delaySaoDiJiCommandQueue, routingKey: routeKeyDelaySaoDiJi);

                    //繫結死信交換機到洗衣機執行命令的延時佇列
                    channel.QueueBind(exchange: exchangeDeadLetter, queue: delayXiYiJiCommandQueue, routingKey: routeKeyDelayXiYiJi);

                    //建立業務交換機
                    channel.ExchangeDeclare(exchange: exchangeBusiness, type: ExchangeType.Direct, durable: true, autoDelete: false);

                    //建立掃地機命令業務佇列
                    Dictionary<string, object> dic1 = new Dictionary<string, object>();
                    dic1.Add("x-expires", 30 * 6 * 10000); //30分鐘後掃地機命令業務佇列自動幹掉
                    dic1.Add("x-message-ttl", 10 * 6 * 10000);//設定訊息在掃地機命令業務佇列中的存活時間,即過期時間(訊息如果10分鐘內沒有消費,就會放入掃地機執行命令的延時佇列裡)
                    dic1.Add("x-dead-letter-exchange", exchangeDeadLetter);//過期訊息轉向路由  
                    dic1.Add("x-dead-letter-routing-key", routeKeyDelaySaoDiJi);//設定死信交換機的路由key,死信交換機會根據路由key去找到對應的延遲佇列
                    channel.QueueDeclare(queue: queueBusinessSaoDiJiCommand, durable: true, exclusive: false, autoDelete: false, arguments:dic1);
                    //繫結業務交換機到掃地機命令業務佇列
                    channel.QueueBind(queue: queueBusinessSaoDiJiCommand, exchange: exchangeBusiness, routingKey: routeKeyBusinessSaoDiJiCommand);


                    //建立洗衣機命令業務佇列
                    Dictionary<string, object> dic2 = new Dictionary<string, object>();
                    dic2.Add("x-expires", 30 * 6 * 10000); //30分鐘後洗衣機命令業務佇列自動幹掉
                    dic2.Add("x-message-ttl", 20 * 6 * 10000);//設定訊息在洗衣機命令業務佇列中的存活時間,即過期時間(訊息如果20分鐘內沒有消費,就會放入洗衣機執行命令的延時佇列裡)
                    dic2.Add("x-dead-letter-exchange", exchangeDeadLetter);//過期訊息轉向路由  
                    dic2.Add("x-dead-letter-routing-key", routeKeyDelayXiYiJi);//過期訊息轉向路由相匹配routingkey  
                    channel.QueueDeclare(queue: queueBusinessXiYiJiCommand, durable: true, exclusive: false, autoDelete: false, arguments: dic2);
                    //繫結業務交換機到洗衣機命令業務佇列
                    channel.QueueBind(queue: queueBusinessXiYiJiCommand, exchange: exchangeBusiness, routingKey: routeKeyBusinessXiYiJiCommand);

                    Console.WriteLine("請輸入傳送的內容:");
                    var message = Console.ReadLine();
                    var body = Encoding.UTF8.GetBytes(message);
                  

                    //訊息持久化,既然都要用到死信佇列了,說明這條訊息還是比較重要的
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;

                    if(message.Contains("aa"))
                    {
                        //釋出訊息到掃地機命令業務佇列
                        channel.BasicPublish(exchange: exchangeBusiness,
                                             routingKey: routeKeyBusinessSaoDiJiCommand,
                                             basicProperties: properties,
                                             body: body);
                    }
                    else
                    {
                        //釋出訊息洗衣機命令業務佇列
                        channel.BasicPublish(exchange: exchangeBusiness,
                                             routingKey: routeKeyBusinessXiYiJiCommand,
                                             basicProperties: properties,
                                             body: body);
                    }

                }
            }
        }
    }
}