服务异步通讯(RabbitMQ)

性能下降,吞吐量下降

实际操作

RabbitMQ安装

导入tar包

启动容器

docker run \
-e RABBITMQ_DEFAULT_USER=itcast \ 这是用户名
-e RABBITMQ_DEFAULT_PASS=123321 \ 用户密码
--name mq \ 容器名
--hostname mq1 \ 主机名,集群部署的时候需要
-p 15672:15672 \ 注册中心
-p 5672:5672 \ 消息处理端口
-d \
rabbitmq:3-management

访问 192.168.81.131:15672

成功

实际操作

定义多个消费者,从而避免消息的堆积

实践开始

  1. Work Queue 一个队列绑定多个消费者

Publisher

在1s内发送50条消息,每条消息间隔20ms避免消息发送过快

Consumer

定义了2个消费者,这2个消费者都从同一个消费队列simple.queue中拿取消息,预期效果是在1s内接收Publisher发送的50条消息

发现这两个消费者分别承担了25条消息,这和我们的预期不符合,因为设置的Thread.sleep,模拟了2个处理速度不同的消费者,我们希望的是能者多劳。

这种现象是RabbitMQ的消息预置,也就是无论消费者是否处理完毕,消费者都会先接收消息,默认的情况下消息预置的上限是无限,我们可以通过修改消费者配置文件中的listener.simple.prefetch来设置消费预置的上限

达到能者多劳的效果了

2. 发布订阅模式

发布订阅模式本质是通过一个交换机对各个需要传输的队列进行消息的传输,所以我们需要首先设置一个交换机的类,这个类又需要交给SpringBoot来管理,所以需要声明为Bean

  1. Fanout 广播队列

首先我们给Publisher定义一个新的配置类

这个配置类中需要定义Exchange交换机,队列 Queue,交换机和队列的绑定关系Binding

配好之后可以通过

发送消息到队列

之后写消费者,消费者区别不大

运行结果

  1. Direct 路由

首先配置配置类,路由相比于广播,增加了一个routingKey,消费者在获取消息的时候会用自己的routingkey于消息的routingKey对比,符合才会获取对应的消息

在Direct配置类中,只需要声明队列和交换机,绑定关系写在对应消费者的注解上

消费者编写如下

发送消息的时候携带routingKey

此时,因为消费者存在2个红色,则这两个消费者都可以收到消息

当routingKey为blue的时候,就只有blue接收到了消息

在全体消费者拥有相同的routingKey的时候,Direct队列可以模拟Fanout队列

  1. Topic 话题

首先编写配置类,于Direct几乎相同

编写消费者

@Exchange中,type的默认类型是Direct,所以Direct的时候没有指定

Topic可以实现routingKey的通配符

通配符规则:# 匹配一个或多个词,* 匹配不多不少恰好1个词

发送消息

此时会匹配上 china.# 和 #.news

此时只会匹配上 china.#

消息队列传输消息的类型可以是任意类型,如果没有配置对应的消息转换器,那么默认SpringBoot底层会采用base64编码,这种编码方式的编码长度较长,不推荐,推荐使用的是Json编码的方式

首先需要引入依赖,在消费者和发布者中都需要引入对应的JSON转换依赖,可以直接在父工程中引入

之后需要在消费者和发布者中都定义一个MessageConvert类型的Bean,来代替默认的MessageConvertBean

发布者

消费者

发送消息

发送成功

现在获取消息

RabbitMQ初步学习结束