MQ,中文是消息队列(MessageQueue),字面来看就是存放消息的队列。

几种常见MQ的对比:

RabbitMQ ActiveMQ RocketMQ Kafka
公司/社区 Rabbit Apache 阿里 Apache
开发语言 Erlang Java Java Scala&Java
协议支持 AMQP,XMPP,SMTP,STOMP OpenWire,STOMP,REST,XMPP,AMQP 自定义协议 自定义协议
可用性 一般
单机吞吐量 一般 非常高
消息延迟 微秒级 毫秒级 毫秒级 毫秒以内
消息可靠性 一般 一般

MQ解决什么问题

MQ是一直存在,不过随着微服务架构的流行,成了解决微服务之间问题的常用工具,有以下几种主要的作用:

异步处理:用户注册后,发送注册邮件和注册短信。用户注册完成后,提交任务到 MQ,发送模块并行获取 MQ 中的任务。

系统解耦:比如用注册完成,再加一个发送微信通知。只需要新增发送微信消息模块,从 MQ 中读取任务,发送消息即可。无需改动注册模块的代码,这样注册模块与发送模块通过 MQ 解耦。

流量削峰:秒杀和抢购等场景经常使用 MQ 进行流量削峰。活动开始时流量暴增,用户的请求写入MQ,超过 MQ 最大长度丢弃请求,业务系统接收 MQ 中的消息进行处理,达到流量削峰、保证系统可用性的目的。

日志处理:日志采集方收集日志写入 kafka 的消息队列中,处理方订阅并消费 kafka 队列中的日志数据。

消息通讯:点对点或者订阅发布模式,通过消息进行通讯。如微信的消息发送与接收、聊天室等。

今天介绍RabbitMQ

RabbitMQ是MQ消息队列的一种,我们一般使用的是Spring集合后的SpringAMQP.

SpringAMQP是基于RabbitMQ封装的一套模板,并且还利用SpringBoot对其实现了自动装配,使用起来非常方便。

AMQP 是一种高级消息队列协议.而SpringAMQ是基于AMQP协议制订的一套api规范,提供了模范来发送和接收消息.

SpringAMQP提供了三个功能

  • 自动声明队列、交换机及其绑定关系 (绑关系)
  • 基于注解的监听器模式,异步接收消息 (接收消息)
  • 封装了RabbitTemplate工具,用于发送消息 (发送消息)

SpringAMQP的简单使用步骤:

1.在父工程中引入依赖,(依赖中包含了RabbitMQ的依赖)

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

2.编写消息发送方和消息接收方的配置文件.这里是让rabbitMQ服务端和消息的发送方和接收方建立了联系

spring:rabbitmq:host: 192.168.150.100 # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机username: username # 用户名password: 1234 # 密码

3.在消息的接收方,新建一个类用来监听发送方发出的消息.

@Component
public class SpringRabbitListener {@RabbitListener(queues = "simple.queue")public void listenSimpleQueueMessage(String msg) throws InterruptedException {System.out.println("spring 消费者接收到消息:【" + msg + "】");}
}

注意这个类是要交给Spring管理的所以加上@Component.监听的动作交给Spring,如果监听到这个队列中有消息,就会接收到,不用我们自己进行任何的操作

4.在消息的发送方,使用RabbitTemplet来发送消息到消息队列

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAmqpTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void testSimpleQueue() {// 队列名称String queueName = "simple.queue";// 消息String message = "hello, spring amqp!";// 发送消息rabbitTemplate.convertAndSend(queueName, message);}
}

这是个简单的发送和接收的例子.

完整的消息的发送涉及到的对象及步骤,消息生产者Producer首先和RabbitMQ服务器建立连接,获取通道channel, 然后生产者发送消息给指定的虚拟机中的交换机,交换机交换机根据消息的routingKey将消息路由(转发)给指定的队列.然后消费者Consumer首先也是和Rabbit建立连接,获取通道channel,然后消费者监听指定的队列,如果监听的队列Queue中有消息了,就可以从消息队列中获取到Producer发送的的\消息了.

完整架构如下所示:

发布/订阅

发布订阅的模型如图:

可以看到,在订阅模型中,多了一个exchange角色,而且过程略有变化:

  • Publisher:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是发给X(交换机)
  • Exchange:交换机,图中的X。一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有以下3种类型:
    • Fanout:广播,将消息交给所有绑定到交换机的队列
    • Direct:定向,把消息交给符合指定routing key 的队列
    • Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
  • Consumer:消费者,与以前一样,订阅队列,没有变化
  • Queue:消息队列也与以前一样,接收消息、缓存消息。

Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!

具体的实现流程:

  1. 导入依赖 作用:引入一个Rabbit服务器,

    <!--AMQP依赖,包含RabbitMQ--><dependency>  <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-amqp</artifactId></dependency>
    
  2. 编写消息发送者和消息接收者(消费者)的yml配置文件 作用: 和引入的Rabbit服务器建立联系,获取通道channel (Spring自动完成)

    spring:rabbitmq:host: 192.168.100.100 # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机username: usname # 用户名password: 123456 # 密码
    
  3. 在消息的接收方这边创建监听. (通过注解@RabbitListener 声明出队列和交换机)

    @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"), exchange = @Exchange(name = "itcast.direct",  type = ExchangeTypes.DIRECT),key = {"red","blue"}  //队列的标签key 与交换机的key做匹配
    ))
    
  4. 在消息生产者这边引用RabbitTemplate对象发送消息(Spring管理着这个RabbitTemplate的Bean,自动注入就可以使用)给交换机

  5. 交换机是消费者的接收方声明的.发送发也可以声明,这里有常用的几种类型的交换机

    Exchange:常用以下3种类型:

    • Fanout:广播,将消息交给所有绑定到交换机的队列
    • Direct:定向,把消息交给符合指定routing key 的队列
    • Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
  6. 交换机根据不同的routingkey把消息转发给匹配的消息队列,消费者监听者监听的通道中有了交换机转发的消息就获取消息.

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

    • Topic交换机接收的消息RoutingKey必须是多个单词,以 **.** 分割
    • Topic交换机与队列绑定时的bindingKey可以指定通配符
    • #:代表0个或多个词
    • *:代表1个词

    这里边消息的发送存在一个消息转化的问题,Spring使用的是jdk的消息序列化器,会把你发送的消息序列化为字节发送给MQ,接收消息的时候,还会把字节反序列化为Java对象。DK序列化存在下列问题:

    • 数据体积过大
    • 有安全漏洞
    • 可读性差

    JDK序列化方式并不合适。我们希望消息体的体积更小、可读性更高,因此可以使用JSON方式来做序列化和反序列化。

    具体的实现

    ​ 就是导入依赖在消息接收的和发送的都需要导入,一个序列化,一个反序列化

    <dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>2.9.10</version>
    </dependency>
    

    ​ 在消息接收的和发送的启动类中添加一个Bean即可,Spring启动的时候,发现有这个bean就不创建这个了,直接管理这个bean

    @Bean
    public MessageConverter jsonMessageConverter(){return new Jackson2JsonMessageConverter();
    }
    

    在spring中有一个简单的配置,可以解决

    多个消息接收器处理能力不同的的情况下,我们想让能力强的多处理,也就是处理完了消息就从消息对列中拿消息去处理,能力少的根据能力处理多少.默认是多个消息处理器轮询分发消息,平均每个处理器获取到的消息是一样的,但是我们可以通过设置prefetch来控制消费者预取的消息数量,从而达到能者多劳的效果

      rabbitmq:listener:simple:prefetch: 1 # 每次只能获取一条消息,处理完成才能获取下一个消息
    

学习随笔记录>>>>有不对.欢迎指教

初识MQ和RabbitMQ相关推荐

  1. RabbitMQ 服务异步通信 -- 初识MQ(同步通信和异步通信、MQ、几种常见MQ的对比)、RabbitMQ安装和介绍

    文章目录 1. 初识MQ 1.1 同步通信和异步通信 1.1.1 同步通信存在的问题 1.1.2 同步调用小结 1.1.3 异步通讯 1.1.4 异步调用方案 1.1.5 异步调用小结 1.2 什么是 ...

  2. [喵咪MQ(1)]RabbitMQ简单介绍准备工作

    [喵咪MQ(1)]RabbitMQ简单介绍准备工作 前言 哈喽大家好呀! 看标题就知道我们这次要讲MQ,之前博客中有提到的KafKa理论上来说也是一个优秀的MQ队列软件,比较知名的MQ有:Go语言编写 ...

  3. 【MQ】MQ消息中间件RabbitMQ

    第一部分:RabbitMQ 一.MQ 概念 MQ,Message Queue,消息队列.本质是队列,遵循FIFO先进先出原则.只不过队列中存放的内容是message而已,还是一种跨进程的通信机制,用于 ...

  4. 初识消息队列/RabbitMQ详解

    欢迎大家阅读<朝夕Net社区技术专刊> 我们致力于.NetCore的推广和落地,为更好的帮助大家学习,方便分享干货,特创此刊!很高兴你能成为忠实读者,文末福利不要错过哦! 今天来给大家分享 ...

  5. linux qos mq,Pika + RabbitMQ:将basic_qos设置为prefetch = 1仍然会消耗队列中的所有消息...

    我有一个python工作者客户端,它可以让10个工人分别挂接到一个RabbitMQ队列中.有点像这样: #!/usr/bin/python worker_count=10 def mqworker(q ...

  6. MQ和RabbitMQ作用特点

    https://blog.csdn.net/weixin_40792878/article/details/82555791

  7. 消息中间件MQ与RabbitMQ面试题(2020最新版)

    Java面试总结(2021优化版)已发布在个人微信公众号[技术人成长之路],优化版首先修正了读者反馈的部分答案存在的错误,同时根据最新面试总结,删除了低频问题,添加了一些常见面试题,对文章进行了精简优 ...

  8. 服务异步通信RabbitMQ

    服务异步通信 目录 1. 初识MQ 2. RabbitMQ快速入门 3. SpringAMQP 最后 目录 1. 初识MQ 同步通讯 直播.微服务间基于Feign的调用 问题:耦合高.性能下降(调用耗 ...

  9. 初识RabbitMQ与 SpringAMQP

    初识MQ 同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话,需要实时响应. 异步通讯:就像发邮件,不需要马上回复. 两种方式各有优劣,打电话可以立即得到响应,但是你却不能跟多个 ...

最新文章

  1. java在线阅读word_java在线预览txt、word、ppt、execel,pdf代码
  2. android软件更新模块实现的技术和方法,Android APK签名原理及方法
  3. OpenCV输出版本和构建配置的实例(附完整代码)
  4. 关于Mysql java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)的问题...
  5. java.util.concurrent.locks.Condition文档说明
  6. leetcode 455. 分发饼干 思考分析
  7. 软件行业渠道的价值在哪里?
  8. oracle中t,Oracle中如何用T
  9. Mybatis原生dao开发方法实现增删改查
  10. (转)关于最近疯狂流行的文件夹变成exe文件的病毒查杀办法
  11. Excel单元格显示数据与实际数据不一致的设置与清除
  12. 体验一下阿里云文字识别OCR
  13. java查找pdf关键字_Java定位PDF中关键字的坐标
  14. 安装磁盘阵列卡的方法
  15. 我的世界正版租赁服务器,《我的世界》【PC版】租赁服务器正式版明日就要和大家见面啦~...
  16. 五年之内,博士学历是否也会开始内卷?
  17. RecyclerView通用适配器
  18. 线性回归-----标准方程法实现线性回归方程
  19. HYOJ 284 坦克大战
  20. 972信息检索 | 第五章 国外综合性信息检索系统

热门文章

  1. Jquery UI中 Dialog对象的作用及常用属性
  2. qurlinfo在qt5中_QT5编译使用QFtp的方法步骤
  3. TF、keras两种padding方式:vaild和same
  4. C++11 智能指针shared_ptr一篇足以
  5. 物联网产业前景看涨然5大挑战在眼前
  6. 电脑小知识:计算机防火墙到底是什么?能不能阻止黑客的入侵?
  7. 手机学习利器Qpython
  8. qpython3.0.0_QPython脚本引擎
  9. Excel实战 第1章 数据处理
  10. IDEA中使用properties连接mysql8.0.13