• RabbitMQ学习笔记(四) Routing


    新的场景

    在我们学习了RabbitMQ的发布与订阅之后,我们很容易就可以完成一个简单的消息群发器。

    使用这个消息群发器,所有的消费者程序实例都会接收到相同的消息信息,从而实现广播的效果。

    但是这种广播是一种无意识的广播,即使消息是有分类的,消费者程序也不能自己决定关注的消息类型,只能被动的接收所有的消息,这就导致消费者程序收到许多无用的消息。

    如果想要消费者程序自主决定关注的消息类型,我们可以使用RabbitMQ的Routing机制。

    Binding

    之前学习RabbitMQ的发布与订阅,我们使用如下代码将消息队列和Exchange进行绑定。

    channel.QueueBind(queue: queueName, exchange: "broadcast", routingKey: "");

    其中有一个参数是routingKey, 我们将它设置为空。

    对于fanout类型的Exchange, 在绑定消息队列和Exchange的时候,会自动忽略routingKey。

    但是Direct类型的Exchange使用这个参数可以帮助我们对消息进行的分类,这里我们可以简单的认为routingKey就是一种消息类型

    Direct Exchange

    Direct的路由算法很简单,它会将消息发送到与Direct  Exchange绑定并拥有指定routingKey的消息队列中。

     

    一个消息队列与一个Direct Exchange绑定的时候,可以通过多次绑定,拥有多个routingKey。

    同理,一个routingKey也可以被多个消息队列拥有。

    例:

    channel.QueueBind(queue: queueName, exchange: "broadcast", routingKey: "key1");
    
    channel.QueueBind(queue: queueName, exchange: "broadcast", routingKey: "key2");



    在发布与订阅中,我们使用生产者程序向Fanout Exchange发送消息的时候,编写了如下代码

    channel.BasicPublish(exchange: "broadcast",
    
                            routingKey: "",
    
                            basicProperties: null,
    
                            body: body
    
                        );



    其中routingKey为空, 因为Fanout Exchange并不关心routingKey。

    现在我们使用Direct Exchange, 我们需要指定消息类型routingKey。当Direct Exchnage接收到这条消息之后,它查找和他绑定的所有消息队列,如果消息队列拥有这个routingKey,Direct Exchange就会将这条消息传输给它, 这样监听该消息队列的消费者程序就可以接收到这条消息。

    修改代码

    Send

    1. Send可以发送3种类型的消息, game, sport, music
    2. 发送消息时必须指定消息的类型

           

    static string[] availableTypes = { "game", "music", "sport" };
    
     
    
            static void Main(string[] args)
    
            {
    
                if (args == null || args.Length == 0)
    
                {
    
                    Console.WriteLine("This command line should be like 'dotnet run [message type] [message].'");
    
                    Environment.Exit(1);
    
                }
    
     
    
                var messageType = args[0];
    
     
    
                if (!availableTypes.Contains(messageType))
    
                {
    
                    Console.WriteLine("Available message type can be 'game','music','sport'.");
    
                    Environment.Exit(1);
    
                }
    
     
    
                var factory = new ConnectionFactory()
    
                {
    
                    HostName = "localhost"
    
                };
    
     
    
                using (var connection = factory.CreateConnection())
    
                {
    
                    using (var channel = connection.CreateModel())
    
                    {
    
                        channel.ExchangeDeclare("broadcast", "direct");
    
     
    
                        string message = $"{args[0]} news: {args[1]}";
    
                        var body = Encoding.UTF8.GetBytes(message);
    
     
    
                        channel.BasicPublish(exchange: "broadcast",
    
                            routingKey: messageType,
    
                            basicProperties: null,
    
                            body: body
    
                        );
    
     
    
                        Console.WriteLine("[x] Sent {0}", message);
    
                    }
    
                }
    
            }

    Receive

    1. Receive可以接收3种类型的消息, game, sport, music
    2. 程序启动时指定接收的消息类型

           

    static string[] availableTypes = { "game", "music", "sport" };
    
     
    
            static void Main(string[] args)
    
            {
    
                if (args == null || args.Length == 0)
    
                {
    
                    Console.WriteLine("This command line should be like 'dotnet run [message type 1] [message type 2] [message type 3].'");
    
                    Environment.Exit(1);
    
                }
    
     
    
                foreach (var type in args)
    
                {
    
                    if (!availableTypes.Contains(type))
    
                    {
    
                        Console.WriteLine("Available message type can be 'game','music','sport'.");
    
                        Environment.Exit(1);
    
                    }
    
                }
    
     
    
                var factory = new ConnectionFactory() { HostName = "localhost" };
    
     
    
                using (var connection = factory.CreateConnection())
    
                {
    
                    using (var channel = connection.CreateModel())
    
                    {
    
                        channel.ExchangeDeclare("broadcast", "direct");
    
     
    
                        var queueName = channel.QueueDeclare().QueueName;
    
     
    
                        foreach (var type in args)
    
                        {
    
                            channel.QueueBind(queue: queueName, exchange: "broadcast", routingKey: type);
    
                        }
    
     
    
                        var consumer = new EventingBasicConsumer(channel);
    
     
    
                        consumer.Received += (model, ea) =>
    
                        {
    
                            var body = ea.Body;
    
                            var message = Encoding.UTF8.GetString(body);
    
                            Console.WriteLine("[x] Received {0}", message);
    
                        };
    
     
    
                        channel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer);
    
     
    
                        Console.Read();
    
                    }
    
                }
    
            }

    最终效果

    启动1个Send, 2个Receive。

    一个Receive关注game, music类型的消息。

    一个Receive关注sport, game类型的消息。

  • 相关阅读:
    (数据科学学习手札21)sklearn.datasets常用功能详解
    (数据科学学习手札20)主成分分析原理推导&Python自编函数实现
    (数据科学学习手札19)R中基本统计分析技巧总结
    (数据科学学习手札18)二次判别分析的原理简介&Python与R实现
    P2633|主席树+dfs序+树链剖分求lca+离散化
    主席树|求区间第k小模板
    树上问题
    数据结构|序列问题与树上问题小结
    珂朵莉树 例题小结
    CF#609E|二分+树状数组
  • 原文地址:https://www.cnblogs.com/lwqlun/p/9095123.html
Copyright © 2020-2023  润新知