RabbitMQ

RabbitMQ

思维导图

img

什么是消息队列

消息指的是两个应用间传递的数据。数据的类型有很多种形式,可能只包含文本字符串,也可能包含嵌入对象。

“消息队列(Message Queue)”是在消息的传输过程中保存消息的容器。在消息队列中,通常有生产者和消费者两个角色。生产者只负责发送数据到消息队列,谁从消息队列中取出数据处理,他不管。消费者只负责从消息队列中取出数据处理,他不管这是谁发送的数据。

img

为什么使用消息队列

主要有三个作用:

  • 解耦。如图所示。假设有系统B、C、D都需要系统A的数据,于是系统A调用三个方法发送数据到B、C、D。这时,系统D不需要了,那就需要在系统A把相关的代码删掉。假设这时有个新的系统E需要数据,这时系统A又要增加调用系统E的代码。为了降低这种强耦合,就可以使用MQ,系统A只需要把数据发送到MQ,其他系统如果需要数据,则从MQ中获取即可

img

  • 异步。如图所示。一个客户端请求发送进来,系统A会调用系统B、C、D三个系统,同步请求的话,响应时间就是系统A、B、C、D的总和,也就是800ms。如果使用MQ,系统A发送数据到MQ,然后就可以返回响应给客户端,不需要再等待系统B、C、D的响应,可以大大地提高性能。对于一些非必要的业务,比如发送短信,发送邮件等等,就可以采用MQ。

img

  • 削峰。如图所示。这其实是MQ一个很重要的应用。假设系统A在某一段时间请求数暴增,有5000个请求发送过来,系统A这时就会发送5000条SQL进入MySQL进行执行,MySQL对于如此庞大的请求当然处理不过来,MySQL就会崩溃,导致系统瘫痪。如果使用MQ,系统A不再是直接发送SQL到数据库,而是把数据发送到MQ,MQ短时间积压数据是可以接受的,然后由消费者每次拉取2000条进行处理,防止在请求峰值时期大量的请求直接发送到MySQL导致系统崩溃

img

RabbitMQ的特点

RabbitMQ是一款使用Erlang语言开发的,实现AMQP(高级消息队列协议)的开源消息中间件。首先要知道一些RabbitMQ的特点,官网可查:

  • 可靠性。支持持久化,传输确认,发布确认等保证了MQ的可靠性。
  • 灵活的分发消息策略。这应该是RabbitMQ的一大特点。在消息进入MQ前由Exchange(交换机)进行路由消息。分发消息策略有:简单模式、工作队列模式、发布订阅模式、路由模式、通配符模式。
  • 支持集群。多台RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker。
  • 多种协议。RabbitMQ支持多种消息队列协议,比如 STOMP、MQTT 等等。
  • 支持多种语言客户端。RabbitMQ几乎支持所有常用编程语言,包括 Java、.NET、Ruby 等等。
  • 可视化管理界面。RabbitMQ提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker。
  • 插件机制。RabbitMQ提供了许多插件,可以通过插件进行扩展,也可以编写自己的插件。

RabbitMQ中的组成部分

从上面的HelloWord例子中,我们大概也能体验到一些,就是RabbitMQ的组成,它是有这几部分:

  • Broker:消息队列服务进程。此进程包括两个部分:Exchange和Queue。
  • Exchange:消息队列交换机。按一定的规则将消息路由转发到某个队列
  • Queue:消息队列,存储消息的队列。
  • Producer:消息生产者。生产方客户端将消息同交换机路由发送到队列中。
  • Consumer:消息消费者。消费队列中存储的消息。

这些组成部分是如何协同工作的呢,大概的流程如下,请看下图:

img

  • 消息生产者连接到RabbitMQ Broker,创建connection,开启channel。
  • 生产者声明交换机类型、名称、是否持久化等。
  • 生产者发送消息,并指定消息是否持久化等属性和routing key。
  • exchange收到消息之后,根据routing key路由到跟当前交换机绑定的相匹配的队列里面。
  • 消费者监听接收到消息之后开始业务处理。

RabbitMQ的队列形式

在使用RabbitMQ之前,咱们先捋一捋RabbitMQ一共有几种使用方式,常用的5中队列

img

  • 第一种:简单队列(一对一模式)耦合性高,生产消费一一对应。
  • 第二种:WorkQueues(工作队列),一个生产,多个消费者共同处理消息。
  • 第三种:订阅模式,1一个生产者多个消费者,每一个消费者有自己的一个队列,生产者直接将消息发送给交换机,交换机将消息发送给队列,每一个队列都需要绑定到交换机。这种模式可以满足消费者发布一个消息,多个消费者消费同一信息的需求,但C1、C2消费的都是相同的数据,有时我们需要C1和C2消费的信息只有部分差异,比如我们需求:C1消费增加的数据,C2消费编辑、增加和删除的数据。
  • 第四种:路由模式,路由模式是在订阅模式基础上的完善,可以在生产消息的时候,加入Key值,与key值匹配的消费者消费信息。但路由模式中,就如三中提到的C1、C2、如果C2对应的类型更多,就需要写很多key值。但其实它只与C1有一点差别。

img

  • 第五种:通配符模式是在路由模式的升级,他允许key模糊匹配。*代表一个词,#代表一个或多个词。通过通配符模式我们就可以将C1对应的一个key准确定为item.add。而C2我们就不需要一一写出key值,而是用item.#代替即可。

img

RabbitMQ安装

安装RabbitMQ (Win10系统)

由于只是学习需要,所以安装在win10系统,就懒得开虚拟机。如果用Linux系统安装的话,我建议用Docker拉一个RabbitMQ的镜像下来,这样会方便一点。

安装erLang语言,配置环境变量

首先到erlang官网下载win10版安装包。

img

下载完之后,就得到这个东西:

img

接着双击安装,一直点next(下一步)就行了,安装完之后,配置环境变量。

img

img

使用cmd命令,输入 erl -version 验证:

img

安装RabbitMQ服务端

在RabbitMQ的gitHub项目中,下载window版本的服务端安装包。

img

下载后,就得到这个东西:

img

接着到双击安装,一直点下一步安装即可,安装完成后,找到安装目录:

img

在此目录下打开cmd命令,输入rabbitmq-plugins enable rabbitmq_management命令安装管理页面的插件:

img

然后双击rabbitmq-server.bat启动脚本,然后打开服务管理可以看到RabbitMQ正在运行:

img

这时,打开浏览器输入http://localhost:15672,账号密码默认是:guest/guest

img

到这一步,安装就大功告成了!

img

.net Core3.1如何优雅的使用RabbitMQ

img

新建控制台应用程序,引入RabbitMQ.Client包

创建生产者

using RabbitMQ.Client;
using System;
using System.Text;

namespace RabbitMQTest
{
    /// <summary>
    /// 生产者
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            //创建连接工厂
            ConnectionFactory factory = new ConnectionFactory
            {
                UserName = "admin",//用户名
                Password = "lmt456123",//密码
                HostName = "localhost"//rabbitmq ip
            };

            //创建连接
            var connection = factory.CreateConnection();
            //创建通道
            var channel = connection.CreateModel();
            //声明一个队列
            channel.QueueDeclare("hello", false, false, false, null);
            Console.WriteLine("\nRabbitMQ连接成功,请输入消息,输入exit退出!");
            string input;
            do
            {
                input = Console.ReadLine();
                var sendBytes = Encoding.UTF8.GetBytes(input);
                //发布消息
                channel.BasicPublish("", "hello", null, sendBytes);
            }
            while (input.Trim().ToLower() != "exit");
            channel.Close();
            connection.Close();
        }
    }
}

创建一对一消费者

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

namespace RabbitMQConsumer
{
    /// <summary>
    /// 消费者
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            //创建连接工厂
            ConnectionFactory factory = new ConnectionFactory
            {
                UserName = "admin",//用户名
                Password = "lmt456123",//密码
                HostName = "localhost"//rabbitmq ip
            };
            //创建连接
            var connection = factory.CreateConnection();
            //创建通道
            var channel = connection.CreateModel();
            //事件基本消费者
            EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
            //接收到消息事件
            consumer.Received += (ch, ea) =>
            {
                string message = Encoding.Default.GetString(ea.Body.ToArray());

                Console.WriteLine($"收到消息: {message}");

                // Console.WriteLine($"收到该消息[{ea.DeliveryTag}] 延迟10s发送回执");
                // Thread.Sleep(10000);
                //确认该消息已被消费
                channel.BasicAck(ea.DeliveryTag, false);
                // Console.WriteLine($"已发送回执[{ea.DeliveryTag}]");
            };
            //启动消费者 设置为手动应答消息
            channel.BasicConsume("hello", false, consumer);
            Console.WriteLine("消费者已启动");
            Console.ReadKey();
            channel.Dispose();
            connection.Close();
        }
    }
}

启动程序并测试

img

一对一的消费队列咱们就此创建完成,下一节开始RabbitMQ的高级用法

原文链接

超详细的RabbitMQ入门,看这篇就够了!:https://developer.aliyun.com/article/769883

RabbitMQ详解(三)------RabbitMQ的五种队列:https://www.cnblogs.com/ysocean/p/9251884.html

.net Core 3.1 使用RabbitMQ(一):https://zhuanlan.zhihu.com/p/143521328

posted @ 2021-11-20 16:51  AJun816  阅读(75)  评论(0编辑  收藏  举报