• 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时间
                        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();
            }
    
             
    
        }
    }

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

    @天才卧龙的博客

  • 相关阅读:
    [刷题] IDA*
    [BZOJ1330] Editing a Book
    [BZOJ5449] 序列
    [刷题] 搜索剪枝技巧
    [XJOI3529] 左右
    [CF920E] Connected Components?
    [第18届 科大讯飞杯 J] 能到达吗
    洛谷 P4779 【模板】单源最短路径(标准版)
    洛谷 P1175 表达式的转换
    pipioj 1291 中缀表达式转后缀表达式I
  • 原文地址:https://www.cnblogs.com/chenwolong/p/RabbitMQ_S.html
Copyright © 2020-2023  润新知