NetCore RabbitMQ 简介及兔子生产者、消费者 【简单模式,work工作模式,竞争消费】

十年河东,十年河西,莫欺少年穷

学无止境,精益求精

先盗用一张图,介绍下RabbitMQ的架构图

简介

 Producer : 生产者

 channel : 通信信道,节约Tcp链接资源

 Broker : MQ Server接点,做集群用的

 VirtualHost : 虚拟机,一个RabbitMQ中可以有多个虚拟机,我们可以通过RabbitMQ提供的可视化网站中创建,虚拟机中可以有多个队列,可以将虚拟机分配不同的用户角色

 Exchange : 交换机 ,代码中可以不指定交换机,不指定交换机时,交换机名称要和队列名称一致。

 Queue : 消息队列

 Consumer : 消费者 

 RabbitMQ 使用的端口如下:

 生产者

关于RabbitMQ的安装请参考:windows环境下,RabbitMQ 安装教程

1、新建一个控制台程序,Nuget引入RabbitMQ.Client

 2、创建如下生产者程序

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

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())
                {
                    //queue : 队列名称
                    //durable : 是否持久化消息,如果设置为true 则会将详细存储在磁盘中
                    //exclusive : 是否设置为独占队列,意思是指只能有一个消费者,设置为false,可以有多个消费者同时消费
                    //autoDelete : 是否是临时队列,临时队列会随着消费者断开连接时自动删除
                    //arguments : arguments 里面有很多属性可以设置,例如队列过期时间等
                    //QueueDeclareOk QueueDeclare(string queue, bool durable, bool exclusive, bool autoDelete, IDictionary<string, object> arguments);
                    Dictionary<string, object> arguments = new Dictionary<string, object>();
                    arguments.Add("x-expires", 45 * 1000); // 队列在一定时间内没被使用,则删除
                    arguments.Add("x-message-ttl", 45 * 1000);//队列中消息的存活1时间  用于延迟消费,也就是指  45秒后 该消息才会被消费
                    channel.QueueDeclare("RabbitMQ", false, false, false, arguments);//创建一个名称为kibaqueue的消息队列
                    var properties = channel.CreateBasicProperties();
                    properties.DeliveryMode = 1; //deliveryMode: 1(nopersistent)非持久化,2(persistent)持久化
                    properties.Priority = 9;//消息的优先级  值越大 优先级越高
                    properties.ContentType = "text/plain";//消息的内输出格式
                    properties.Expiration = (60 * 1000).ToString(); //消息的过期时间为60秒
                    var messages = "I am RabbitMQ"; //传递的消息内容
                    //exchange 交换机,如果使用默认的交换机,那么routingKey要和队列的名称一致
                    //routingKey:路由  
                    //basicProperties : 用于基础属性设置
                    ///BasicPublish(this IModel model, string exchange, string routingKey, IBasicProperties basicProperties, ReadOnlyMemory<byte> body);
                    channel.BasicPublish("", "RabbitMQ", properties, Encoding.UTF8.GetBytes(messages)); //生产消息
                }
            }
            Console.Read();
        }
    }
}

上述代码中需要重点介绍如下注释:QueueDeclareOk QueueDeclare(string queue, bool durable, bool exclusive, bool autoDelete, IDictionary<string, object> arguments);

                    //queue : 队列名称
                    //durable : 是否持久化消息,如果设置为true 则会将详细存储在磁盘中
                    //exclusive : 是否设置为独占队列,意思是指只能有一个消费者,设置为false,可以有多个消费者同时消费
                    //autoDelete : 是否是临时队列,临时队列会随着消费者断开连接时自动删除
                    //arguments : arguments 里面有很多属性可以设置,例如队列过期时间等
                    //QueueDeclareOk QueueDeclare(string queue, bool durable, bool exclusive, bool autoDelete, IDictionary<string, object> arguments);

 autoDelete 设置为true后,队列就变成了临时队列,也就是自动删除的队列

自动删除队列和普通队列在使用上没有什么区别,唯一的区别是,当消费者断开连接时,队列将会被删除。自动删除队列允许的消费者没有限制,也就是说当这个队列上最后一个消费者断开连接才会执行删除。

自动删除队列只需要在声明队列时,设置属性auto-delete标识为true即可。系统声明的随机队列,缺省就是自动删除的。

exclusive 设置为TRUE时,队列就成了单消费者队列

普通队列允许的消费者没有限制,多个消费者绑定到多个队列时,RabbitMQ会采用轮询进行投递。如果需要消费者独占队列,在队列创建的时候,设定属性exclusive为true。

 durable 设置为true 代表永久队列,消息会被存储到磁盘中

持久化队列和非持久化队列的区别是,持久化队列会被保存在磁盘中,固定并持久的存储,当Rabbit服务重启后,该队列会保持原来的状态在RabbitMQ中被管理,而非持久化队列不会被保存在磁盘中,Rabbit服务重启后队列就会消失。

非持久化比持久化的优势就是,由于非持久化不需要保存在磁盘中,所以使用速度就比持久化队列快。即是非持久化的性能要高于持久化。而持久化的优点就是会一直存在,不会随服务的重启或服务器的宕机而消失。

在声明队列时,将属性durable设置为“false”,则该队列为非持久化队列,设置成“true”时,该队列就为持久化队列

 自动过期队列

指队列在超过一定时间没使用,会被从RabbitMQ中被删除。什么是没使用?

一定时间内没有Get操作发生

没有Consumer连接在队列上

特别的:就算一直有消息进入队列,也不算队列在被使用。

通过声明队列时,设定x-expires参数即可,单位毫秒。

关于arguments中的参数,我们可以通过RabbitMQ提供的工具中查看,如下图:

含义如下

 信道的基础属性,代码部分如下:

 var properties = channel.CreateBasicProperties();

属性如下

contentType:消息的内容类型,如:text/plain
contentEncoding:消息内容编码
headers:设置消息的header,类型为Map<String,Object>
deliveryMode:1(nopersistent)非持久化,2(persistent)持久化
priority:消息的优先级
correlationId:关联ID
replyTo:用于指定回复的队列的名称
expiration:消息的失效时间
messageId:消息ID
timestamp:消息的时间戳
type:类型
userId:用户ID
appId:应用程序ID
custerId:集群ID 

以上就是兔子MQ生产者代码构建过程中的详细细节

消费者

代码如下

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

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);
            };
            //启动消费者 
            channel.BasicConsume("RabbitMQ", false, consumer);
            Console.WriteLine("消费者已启动");
            Console.ReadKey();
            channel.Dispose();
            connection.Close();
        }

         

    }
}

可以适当的增加消费者,多个消费者处于竞争状态,加快消息的处理速度。

@天才卧龙的博客

posted @ 2022-07-21 17:49  天才卧龙  阅读(582)  评论(0编辑  收藏  举报