RabbitMQ——六种工作模式实战(.net core)

概述

这边文章接上一篇文章:RabbitMQ——RabbitMQ的六种工作模式详解,以.net core 作为实现方式进行RabbitMQ的六种工作模式实战

简单队列(点对点)

最简单的工作队列,其中一个消息生产者(P),一个消息消费者(C),一个队列。也称为点对点模式

在这里插入图片描述
生产者

public static void SendMessage()
{
    string queueName = "simplest";

    using (var connection = RabbitMQHelper.GetConnection())
    {
        using (var channel = connection.CreateModel())
        {
            channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
            while (true)
            {
                string message = "Simplest Message";
                var body = Encoding.UTF8.GetBytes(message);
                
                channel.BasicPublish(exchange: "", routingKey: queueName, null, body);
                Thread.Sleep(1000);
                Console.WriteLine("Sended Simplest message");
            }
        }
    }
}

我们使用的是默认交换机((AMQP default)direct),在发布(BasicPublish)的时候routingKey需和queue名称一致,否则会丢失消息

消费者

public static void ReceiveMessage()
{
    string queueName = "simplest";

    var connection = RabbitMQHelper.GetConnection();
    var channel = connection.CreateModel();

    channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);

    var consumer = new EventingBasicConsumer(channel);
    consumer.Received += (model, ea) =>
    {
        var message = Encoding.UTF8.GetString(ea.Body.ToArray());
        Console.WriteLine("Simplest Received:{0}", message);
    };
    channel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer);
}

工作队列

一个消息生产者,一个交换器,一个消息队列,多个消费者。同样也称为点对点模式

在这里插入图片描述
生产者

public static void SendMessage()
{
    string queueName = "Worker_Queue";

    using (var connection = RabbitMQHelper.GetConnection())
    {
        using (var channel = connection.CreateModel())
        {
            channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
            for (int i = 0; i < 20; i++)
            {
                string message = $"Worker Queue Message {i}";
                var body = Encoding.UTF8.GetBytes(message);
                channel.BasicPublish(exchange: "", routingKey: queueName, null, body);
                Console.WriteLine($"Sended Message {i}");
            }
        }
    }
}

消费者

public static void ReceiveMessage()
{
    string queueName = "Worker_Queue";
    var connection = RabbitMQHelper.GetConnection();
    {
        var channel = connection.CreateModel();
        {
            channel.QueueDeclare(queueName, false, false, false, null);
            var consumer = new EventingBasicConsumer(channel);
            
            channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
            consumer.Received += (model, ea) => {
                var message = Encoding.UTF8.GetString(ea.Body.ToArray());
                Console.WriteLine(" Worker Queue Received:{0}", message);
            };
            channel.BasicConsume(queueName, true, consumer);
        }
    }
}

公平性队列
通过prefetchCount = 1设置BasicQos,这告诉RabbitMQ,一次不要给一个消费者多条消息。或者换句话说,在未收到消费端的消息确认时,不再分发消息,也就确保了当消费端处于忙碌状态时,不再分配任务。也可以解释为能者多劳

发布订阅

将消息发送给不同类型的消费者。做到发布一次,多个消费者来消费。

在这里插入图片描述

生产者

public static void SendMessage()
{
    using (var connection = RabbitMQHelper.GetConnection())
    using (var channel = connection.CreateModel())
    {
        channel.ExchangeDeclare("fanout_exchange", "fanout", durable: false, autoDelete: false, arguments: null);
        for (int i = 0; i < 3; i++)
        {
            string queueName = $"fanout_queue_{i + 1}";
            channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
            channel.QueueBind(queue: queueName, exchange: "fanout_exchange", routingKey: "", arguments: null);
        }
        for (int i = 0; i < 10; i++)
        {
            string message = $"Fanout Message {i}";
            var body = Encoding.UTF8.GetBytes(message);
            channel.BasicPublish(exchange: "fanout_exchange", routingKey: "", false, null, body);
            Console.WriteLine($"Sended Fanout Message:{i}");
        }
    }
}

消费者

public static void ReceiveMessage()
{
    var connection = RabbitMQHelper.GetConnection();
    var channel = connection.CreateModel();
    channel.ExchangeDeclare("fanout_exchange", "fanout", durable: false, autoDelete: false, arguments: null);

    for (int i = 0; i < 3; i++)
    {
        string queueName = $"fanout_queue_{i + 1}";
        channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
        channel.QueueBind(queue: queueName, exchange: "fanout_exchange", routingKey: "", arguments: null);
    }

    var consumer = new EventingBasicConsumer(channel);
    consumer.Received += (model, ea) =>
    {
        var message = Encoding.UTF8.GetString(ea.Body.ToArray());
        Console.WriteLine("Fanout Received:{0}", message);
    };
    channel.BasicConsume("fanout_queue_1", autoAck: true, consumer);
}

路由模式

在发布/订阅模式的基础上,有选择的接收消息,也就是通过 routing 路由进行匹配条件是否满足接收消息

在这里插入图片描述

生产者

分别往direct_queue_1direct_queue_2direct_queue_3三个队列里各放入10条

public static void SendMessage()
{
    using (var connection = RabbitMQHelper.GetConnection())
    using (var channel = connection.CreateModel())
    {
        channel.ExchangeDeclare("direct_exchange", "direct", durable: false, autoDelete: false, arguments: null);
        for (int i = 0; i < 3; i++)
        {
            string queueName = $"direct_queue_{i + 1}";
            channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
            channel.QueueBind(queue: queueName, exchange: "direct_exchange", routingKey: $"direct_key_{i + 1}", arguments: null);
        }
        
        for (int i = 0; i < 3; i++)
        {
            var tempRoutingKey = $"direct_key_{i + 1}";
            for (int j = 0; j < 10; j++)
            {
                string message = $"Direct Message {j} and RoutingKey:direct_key_{i + 1}";
                var body = Encoding.UTF8.GetBytes(message);
                channel.BasicPublish(exchange: "direct_exchange", routingKey: tempRoutingKey, false, null, body);
                Console.WriteLine($"Sended Message:{j} ****** RoutingKey:direct_key_{i + 1}");
            }
        }
    }
}

注意
队列绑定QueueBind和发送消息BasicPublish的时候需要指定routingKey发送

消费者

消费direct_queue_1的消息

public static void ReceiveMessage()
{
    var connection = RabbitMQHelper.GetConnection();
    var channel = connection.CreateModel();
    channel.ExchangeDeclare("direct_exchange", "direct", durable: false, autoDelete: false, arguments: null);

    for (int i = 0; i < 3; i++)
    {
        string queueName = $"direct_queue_{i + 1}";
        channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
        channel.QueueBind(queue: queueName, exchange: "direct_exchange", routingKey: $"direct_key_{i + 1}", arguments: null);
    }

    var consumer = new EventingBasicConsumer(channel);
    consumer.Received += (model, ea) =>
    {
        var message = Encoding.UTF8.GetString(ea.Body.ToArray());
        var routingKey = ea.RoutingKey;
        Console.WriteLine("Direct Received {0} ****** RoutingKey:{1}", message, routingKey);
        channel.BasicAck(ea.DeliveryTag, true);
    };
    channel.BasicConsume(queue: "direct_queue_1", autoAck: false, consumer: consumer);
}

主题模式

同样是在发布/订阅模式的基础上,根据主题匹配进行筛选是否接收消息。topics 主题模式跟 routing 路由模式类似,只不过路由模式是指定固定的路由键 routingKey,而主题模式是可以模糊匹配路由键routingKey,类似于SQL中 = 和 like 的关系。

在这里插入图片描述
生产者

分别往topic_queue1topic_queue2topic_queue3三个队列里各放入10条

public static void SendMessage()
{
    using (var connection = RabbitMQHelper.GetConnection())
    {
        using (var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare("topic_exchange", "topic");

            string queueName1 = "topic_queue1";
            channel.QueueDeclare(queueName1, false, false, false, null);
            string queueName2 = "topic_queue2";
            channel.QueueDeclare(queueName2, false, false, false, null);
            string queueName3 = "topic_queue3";
            channel.QueueDeclare(queueName3, false, false, false, null);

            channel.QueueBind(queue: queueName1, exchange: "topic_exchange", routingKey: "user.data.#");
            channel.QueueBind(queue: queueName2, exchange: "topic_exchange", routingKey: "user.data.delete");
            channel.QueueBind(queue: queueName3, exchange: "topic_exchange", routingKey: "user.data.update");

            // routingKey:user.data.abc
            for (int i = 0; i < 10; i++)
            {
                string message = $"Topic abc Message {i + 1}";
                var body = Encoding.UTF8.GetBytes(message);
                channel.BasicPublish("topic_exchange", "user.data.abc", null, body);
                Console.WriteLine($"Sended Topic abc Message {i}");
            }
            // routingKey:user.data.abc
            for (int i = 0; i < 10; i++)
            {
                string message = $"Topic delete Message {i + 1}";
                var body = Encoding.UTF8.GetBytes(message);
                channel.BasicPublish("topic_exchange", "user.data.delete", null, body);
                Console.WriteLine($"Sended Topic delete Message {i}");
            }
            // routingKey:user.data.update
            for (int i = 0; i < 10; i++)
            {
                string message = $"Topic update Message {i + 1}";
                var body = Encoding.UTF8.GetBytes(message);
                channel.BasicPublish("topic_exchange", "user.data.update", null, body);
                Console.WriteLine($"Sended Topic update Message {i}");
            }
        }
    }
}

消费者

消费topic_queue1队列的消息,不管routingKey是什么。

public static void ReceiveMessage()
{
    var queueName = "topic_queue1";
 
    var connection = RabbitMQHelper.GetConnection();
    var channel = connection.CreateModel();
    channel.ExchangeDeclare("topic_exchange", "topic", durable: false, autoDelete: false, arguments: null);

    channel.QueueDeclare(queueName, false, false, false, null);
    channel.QueueBind(queue: queueName, exchange: "topic_exchange", routingKey: "user.data.insert");

    var consumer = new EventingBasicConsumer(channel);
    consumer.Received += (model, ea) =>
    {
        var message = Encoding.UTF8.GetString(ea.Body.ToArray());
        var routingKey = ea.RoutingKey;
        Console.WriteLine("Topic Received:{0} ****** RoutingKey:{1}", message, routingKey);
    };
    channel.BasicConsume(queueName, autoAck: true, consumer);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr___Ray

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值