欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RabbitMQ

程序员文章站 2022-07-12 12:48:57
...

RabbitMQ

  • RabbitMQ简介
  • RabbitMQ消息模式
  • RabbitMQ基于SpringBoot应用

一、Rabbit简介

1.RabbitMQ特点

为何使用RabbitMQ?

-RabbitMQ是一个开源的AMQP实现,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。
-用于在分布式系统中存储转发消息,使之组件之间解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
-其中AMQP协议,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。
-AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。

ActiveMQ传递数据量小,对数据量大小有限制但安全可靠 与此相反:Kafka可以处理大量数据,常用于大数据但容易丢失部分数据,不安全可靠
故而RabbitMQ应运而生,即安全可靠又可以传输大量数据

rabbit的queue是手动创建而active是有则使用没有则自动创建

消息是对象则对象需要实现序列化接口

特点

1.可靠性(Reliability)RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。
2.灵活的路由(Flexible Routing)在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。
3.消息集群(Clustering)多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。
    等等...

注意:RabbitMQ底层采用erlang开发;与SpringAMQP完美整合API丰富;

默认端口号:

15672 (if management plugin is enabled)
15671 management监听端口
5672, 5671 (AMQP 0-9-1 without and with TLS)
4369 (epmd) epmd 代表 Erlang 端口映射守护进程
25672 (Erlang distribution)

2.架构和主要概念

graph LR
p(发送消息)-->e[Exchange];
e--RoutingKey-->q[Queue];
q-->c(接收消息);
RabbitMQ服务器-->n个Exchange;
RabbitMQ服务器-->n个Queue;

组成

1.RabbitMQ Server: 也叫broker server,它是一种传输服务。 他的角色就是维护一条从Producer到Consumer的路线,保证数据能够按照指定的方式进行传输。
2.Connection(连接):Producer和Consumer都是通过TCP连接到RabbitMQ Server的。以后我们可以看到,程序的起始处就是建立这个TCP连接。
3.Channels(信道):它建立在上述的TCP连接中。数据流动都是在Channel中进行的。也就是说,一般情况是程序起始建立TCP连接,第二步就是建立这个Channel。每个Channel代表一个会话。 
4.VirtualHost:权限控制的基本单位,用户进行逻辑隔离,用于项目隔离
5*.Message:消息,服务器和应用程序直接传输的数据
6.Producer: 消息生产者,消息生产者连接RabbitMQ服务器然后将消息投递到Exchange。
7.Consumer:消息消费者订阅队列,RabbitMQ将Queue中的消息发送到消息消费者。
8.Exchange:生产者将消息发送到Exchange(交换器),由Exchange将消息路由到一个或多个Queue中(或者丢弃)。Exchange并不存储消息。RabbitMQ中的Exchange有direct、fanout、topic、headers四种类型,每种类型对应不同的路由规则。
9.Queue:(队列)是RabbitMQ的内部对象,用于存储消息。消息消费者就是通过订阅队列来获取消息的,RabbitMQ中的消息都只能存储在Queue中,生产者生产消息并最终投递到Queue中,消费者可以从Queue中获取消息并消费。多个消费者可以订阅同一个Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。
10.Routing key:生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路规则,而这个routing key需要与Exchange Type及binding key联合使用才能最终生效。在Exchange Type与binding key固定的情况下(在正常使用时一般这些内容都是固定配置好的),我们的生产者就可以在发送消息给Exchange时,通过指定routing key来决定消息流向哪里。RabbitMQ为routing key设定的长度限制为255bytes。

二、RabbitMQ消息模式

1.直列模式Direct

我们需要将消息发给唯一 一个节点时使用这种模式,这是最简单的一种形式。
任何发送到Direct Exchange的消息都会被转发到RouteKey中指定的Queue。

Direct Exchange

graph LR
routing_key=KEY-->b(Broker);
b-->e(Exchange);
e--无需Bindings-->q[Queues];
q--转发到指定的Queue-->KEY:队列名;
q-->q2;
q-->...;
1.一般情况可以使用rabbitMQ自带的Exchange:""(该Exchange的名字为空字符串,下文称其为default Exchange)。
2.这种模式下不需要将Exchange进行任何绑定(binding)操作
3.消息传递时需要一个“RouteKey”,可以简单的理解为要发送到的队列名字。
4.如果vhost中不存在RouteKey中指定的队列名,则该消息会被抛弃

注:此模式仅需创建队列

生产者:

  1. 依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
        <version>2.0.1.RELEASE</version>
    </dependency>
    
  2. 配置文件application.yml
    server:
      port: 8080
    spring:
      rabbitmq:  #配置rabbitMQ的服务器地址和端口号
        addresses: 127.0.0.1  
        port: 5672
    
  3. 消息传输的实体类需要实现序列化接口
  4. 测试类
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    User user= new User();
     //参数一:队列名称 参数二:消息内容
    rabbitTemplate.convertAndSend("queue-1", user);
    
    

消费者

  1. 依赖配置同上
  2. 测试类
    @Component//被修饰的类由Spring容器管理
    @RabbitListener(queues="queue-1")//消息监听器  修饰类  被修饰的类为消费者类
    
    @RabbitHandler//修饰方法  被修饰的方法 参数类型必须和发送的消息类型一致
    

2.分列模式Fanout

当我们需要将消息一次发给多个队列时,需要使用这种模式。

Fanout Exchange

graph LR
Message-->b(Broker);
b-->e(Exchange);
e--Bingdings-->q[Queues];
q--转发到与该Exchange绑定的所有Queue-->1[...];
q-->2[...];
q-->...;
任何发送到Fanout Exchange的消息都会被转发到与该Exchange绑定(Binding)的所有Queue上。
1.可以理解为路由表的模式
2.这种模式*不需要RouteKey
3.这种模式*需要提前将Exchange与Queue进行绑定,一个Exchange可以绑定多个Queue,一个Queue可以同多个Exchange进行绑定。
4.如果接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃。

注:此模式需要创建队列绑定Exchange(交换器)

生产者

API:

@Autowired
    private RabbitTemplate rabbitTemplate;
    
    User user= new User();
     //参数一:交换器名称 参数二:消息内容
    rabbitTemplate.convertAndSend(exchange:"exchange-1",routingKey:"", user);//无需指定路由key

消费者
API:

@Component
@RabbitListener(queues="queue-a")//监听队列消息

@RabbitHandler//修饰方法

3.主题模式Topic

任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue

Topic Exchange

graph LR
routing_key=usa.news--Broker-->e(Exchange);
routing_key=usa.weather--Broker-->e;

e--Bingdings_news_weather-->binding_key=usa.#;
e--Bingdings_news-->bindings_key=#.news;
e--Bingdings_weather-->bindings_key=#.weather;
此类交换器使得来自不同的源头的消息可以到达一个对列,其实说的更明白一点就是模糊匹配的意思,
例如:上图中红色对列的routekey为usa.#,#代表匹配任意字符,但是要想消息能到达此对列,usa.必须匹配后面的#好可以随意。
图中usa.news,usa.weather,都能找到红色队列,符号 # 匹配一个或多个词,符号 * 匹配不多不少一个词。因此 usa.# 能够匹配到 usa.news.XXX ,但是 usa.* 只会匹配到 usa.XXX 。

注:
交换器说到底是一个名称与队列绑定的列表。当消息发布到交换器时,实际上是由你所连接的信道,将消息路由键同交换器上绑定的列表进行比较,最后路由消息。任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue上
1.这种模式较为复杂,简单来说,就是每个队列都有其关心的主题,所有的消息都带有一个“标题”(RouteKey),Exchange会将消息转发到所有关注主题能与RouteKey模糊匹配的队列。
2.这种模式需要RouteKey,也许要提前绑定Exchange与Queue。
3.在进行绑定时,要提供一个该队列关心的主题,如“#.log.#”表示该队列关心所有涉及log的消息(一个RouteKey为”MQ.log.error”的消息会被转发到该队列)。
4.“#”表示0个或若干个关键字,“*”表示一个关键字。如“log.*”能与“log.warn”匹配,无法与“log.warn.timeout”匹配;但是“log.#”能与上述两者匹配。
5.同样,如果Exchange没有发现能够与RouteKey匹配的Queue,则会抛弃此消息
 

注意:此模式需要创建队列和交换器,交换器需要绑定路由

生产者

@Autowired
    private RabbitTemplate rabbitTemplate;
    
    User user= new User();
     //参数一:交换器名称 参数二:路由名称 参数三:消息内容
    rabbitTemplate.convertAndSend(exchange:"exchange-2",routingKey:"user.news", object:"路由消息");//指定交换器,路由

消费者:

同上@RabbitListener,@RabbitHandler

三、SpringBoot整合RabbitMQ