06SpringCloud-MQ

这一部分的笔记是比较粗略的,原因是我之前学过一遍RabbitMq,所以就快速的跟着视频复习了一遍,然后我之前有总结RabbitMQ常用的命令和集群方面的搭建。参考我这篇文章:
RabbitMQ个人总结

1. 初识MQ

同步通讯和异步通讯

image-20211116154346311

手机通讯无法同时跟多人打电话,微信聊天可以同时跟多个人聊天

同步调用

微服务间基于Feign的调用就属于同步方式,存在一些问题:

  1. 耦合度高:每次加入新的需求,都要修改原来的代码
  2. 性能下降:调用者需要等待服务提供者响应,如果调用链过长则响应时间等于每次调用的时间之和。
  3. 资源浪费:调用链中的每个服务在等待响应过程中,不能释放请求占用的资源,高并发场景下会极度浪费系统资源
  4. 级联失败:如果服务提供者出现问题,所有调用方都会跟着出问题,如同多米诺骨牌- -样,迅速导致整个微服务群故障

总结

同步调用的优点:

  1. 时效性较强,可以立即得到结果

同步调用的问题:

  1. 耦合度高
  2. 性能和吞吐能力下降
  3. 有额外的资源消耗
  4. 有级联失败问题

异步调用

异步调用常见实现就是事件驱动模式

优势

  1. 服务解耦

  2. 性能提升,吞吐量提高

  3. 服务没有强依赖,不担心级联失败问题(故障隔离)

  4. 流量削峰

缺点:

  1. 依赖于Broker的可靠性、安全性、吞吐能力

  2. 架构复杂了,业务没有明显的流程线,不好追踪管理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1axMra5k-1637069883227)(https://gitee.com/zuckdbg/zuckpicbed/raw/master/img/image-20211116155345031.png)]

什么是MQ

MQ (MessageQueue), 中文是消息队列, 字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。

image-20211116155908330

国内常用RabbitMQ 和 Kafka , Kafka适用于数据安全要求不高的,海量数据,(如日志)

RabbitMQ和 RocketMQ 稳定性更强,可靠性更高,吞吐量不差,适用于稳定性要求高的业务之间的通信。

中小型企业-RabbitMQ,无深度定制要求。

2.RabbitMQ快速入门

RabbitMQ是基于Erlang语言开发的开源消息通信中间件,官网地址: https://www.rabbitmq.com/

1. 单机部署

我们在Centos7虚拟机中使用Docker来安装。

1.下载镜像

方式一:在线拉取

docker pull rabbitmq:3-management

方式二:从本地加载

在课前资料已经提供了镜像包:

image-20211116160406171

上传到虚拟机中后,使用命令加载镜像即可:

docker load -i mq.tar

# 查看docker images 发现导入成功
rabbitmq                    3-management   95bc78c8d15d   17 months ago       187MB

2.安装MQ

docker run \
 -e RABBITMQ_DEFAULT_USER=root \
 -e RABBITMQ_DEFAULT_PASS=123456 \
 --name mq \
 --hostname mq1 \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3-management

3.访问

http://192.168.10.100:15672

image-20211116160844818

2.RabbitMQ的结构和概念

image-20211116161142483

RabbitMQ中的几个概念:

  1. channel: 操作MQ的工具
  2. exchange: 路由消息到队列中
  3. queue: 缓存消息
  4. virtual host:虚拟主机,是对queue、 exchange等资源的逻辑分组

3.消息模型

官方的HelloWorld是基于最基础的消息队列模型来实现的,只包括三个角色:

publisher:消息发布者,将消息发送到队列queue

queue:消息队列,负责接受并缓存消息

consumer:订阅队列,处理队列中的消息

image-20211116161449034

4.入门案例

image-20211116162134525

3.SpringAMQP

image-20211116162240110

3.1 发送消息

步骤一:

在mq-demo项目的父工程pom.xml引入以下依赖:

<!--AMQP依赖,包含RabbitMQ-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

步骤2:

在publisher中编写测试方法,向simple.queue发送消息

image-20211116192628148

总结:

  1. 什么是AMQP?

    应用间消息通信的一种协议,与语言和平台无关。

  2. SpringAMQP如何发送消息?

    引入amqp的starter依赖,配置RabbitMQ地址

    利用RabbitTemplate的convertAndSend方法

3.2 接收消息

image-20211116193036825

启动Consumer服务

image-20211116193515904

SpringAMQP如何接收消息?

  1. 引入amqp的starter依赖
  2. 配置RabbitMQ地址
  3. 定义类,添加@Component注解
  4. 类中声明方法,添加@RabbitListener注解,方法参数就时消息

3.3 WorkQueue工作队列

image-20211116194031040

image-20211116194135560

 @Test
public void testSendMsgWorkQueue() throws InterruptedException {
    String queueName = "simple.queue";
    String message = "hello,message __ ";

    for (int i = 1; i <= 50; i++) {
        rabbitTemplate.convertAndSend(queueName,message + i);
        Thread.sleep(20);
    }
}
package cn.itcast.mq.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author:whd
 * @createTime: 2021/11/16
 */
@Component
public class SpringRabbitListener {
//    @RabbitListener(queues = "simple.queue")
//    public void listenSimpleQueueMessage(String msg) {
//        System.out.println("spring消费者接收到消息:【" + msg + "]");
//    }

    //记录消费者1的消费量
    private Integer count1 = 0;
    //记录消费者2的消费量
    private Integer count2 = 0;

    /**
     * 消费者1,每秒50条消息
     * @param msg
     */
    @RabbitListener(queues = "simple.queue")
    public void listen1WorkQueueMessage(String msg) throws InterruptedException {
        count1++;
        System.out.println("消费者1【处理能力强】接收到消息:【" + msg + "】,当前是消费者1的第"+count1+"条");
        Thread.sleep(20);
    }

    /**
     * 消费者2,每秒10条消息
     * @param msg
     */
    @RabbitListener(queues = "simple.queue")
    public void listen2WorkQueueMessage(String msg) throws InterruptedException {
        count2++;
        System.err.println("消费者2【处理能力强】接收到消息:【" + msg + "】,当前是消费者2的第"+count2+"条");
        Thread.sleep(100);
    }
}

但是怎么让消费能力弱的少拿点消息呢?

3.4 消费预取限制

image-20211116195329717

能提高消息处理速度,这个执行以后,消费者1能力强拿到的消息多(40条),消费者2能力弱拿到的消息少(10条)

3.5 发布订阅模型

image-20211116195813253

1.Fanout Exchange

Fanout Exchange会将接收到的消息路由到每一个跟其绑定的queue

image-20211116195945187

image-20211116195956591

image-20211116200030965

image-20211116201439990

image-20211116201446331

交换机的作用是什么?

  1. 接收publisher发送的消息
  2. 将消息按照规则路由到与之绑定的队列
  3. 不能缓存消息,路由失败,消息丢失
  4. FanoutExchange的会将消息路由到每个绑定的队列

声明队列、交换机、绑定关系的Bean是什么?

  • Queue
  • FanoutExchange
  • Binding

2.Direct Exchange

image-20211116201753467

image-20211116201856786

使用注解方式绑定队列与交换机,并声明bindingkey

image-20211116201913625

image-20211116202949189

描述下Direct交换机与Fanout交换机的差异?

  1. Fanout交换机将消息路由给每一个与之绑定的队列
  2. Direct交换机根据RoutingKey判断路 由给哪个队列
  3. 如果多个队列具有相同的RoutingKey,则与Fanout功能类似

基于@RabbitListener注解声明队列和交换机有哪些常见注解?

@Queue

@Exchange

3.Topic Exchange

image-20211116203221907

image-20211116203230610

image-20211116203521521

image-20211116203527989

描述下Direct交换机与Topic交换机的差异?

Topic支持通配符

3.6 消息转换器

image-20211116203900317

image-20211116203907763

依赖也可以是:jackson核心依赖

<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

总结

image-20211116204340511

思考一下,这种基于MQ的异步通知操作,在哪些业务场景中可以用到呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZuckD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值