RabbitMq

Posted 赵jc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RabbitMq相关的知识,希望对你有一定的参考价值。

Rabbitmq

一为什么使用MQ?

使用MQ的场景很多,主要有三个:解耦、异步、削峰

  • 解耦:A服务可以将消息放在MQ当中,其他的服务可以直接从MQ当中获取消息并进行处理即可,A服务和B服务没有实际的关联,提高了系统的灵活性和扩展性
  • 异步:可以将一些非核心的流程,如日志,短信,右键等通过MQ的方式去异步处理,这样做的好处是缩短主流程的响应时间,提升用户的体验
  • 削峰:MQ的本质就是业务排队,所以面对突然到来的高并发,现在MQ中排好队一个一个来。削峰的好处就是避免高并发压垮系统的关键组件(如某个核心的服务或者数据库等)

解耦场景:A系统发送数据到BCD三个系统,通过接口调用发送,如果E系统也要用这个数据呢?那如果C系统现在不需要用这个数据了呢?A系统负责人几乎崩溃…

如果使用MQ,A系统产生一条数据,发送到MQ里面去,如果那个系统需要数据自己去MQ里面取数据,A系统压根不需要考虑消息发给谁,不需要维护这个代码,也不需要考虑人家是调用成功,失败超时等情况

通过一个MQ,Pub/Sub发布订阅消息 这么一个模型,A系统就跟其他系统彻底解耦了
异步场景:A系统接受了一个请求,需要在自己本地写如数据库,还要在BCD三个系统写入数据库,自己本地需要3ms,BCD三个系统分别需要300ms,450ms,200ms,最终请求的总时延时953ms接近1s,用户体验极差,一般互谅网的企业,对于用户的直接操作,一般要求是每个请求必须在200ms以内完成,对用户几乎是无感知的

如果使用MQ,那么A系统连续发送3条消息到MQ队列当中,假如耗时5ms,A系统从接受一个请求到返回最终响应给用户总是尝试8ms,大大减少了响应时间

削峰场景:每天0:00到12:00,A系统风平浪静,每秒并发请求数量就50个,结果每次一道12:00-13:00美妙的并发请求就会突然暴增到5000个,但A服务最大的处理能力是2000个,所以当大量请求时服务器会垮掉
使用MQ,将5000个请求写入MQ,A系统慢慢从MQ中拉取请求,在自己的能力范围内处理请求就可以了,这样下来哪怕是高峰期,系统也可以正常使用,但是会有大量的请求积压在MQ当中(可能有上百个),但是短暂的高峰期挤压是ok的,因为高峰期过了之后,A系统就会很快地将积压的消息处理掉(高峰期过后,MQ每秒进入50个请求,但是A系统仍然会以2000个请求的速度去处理)

消息队列的缺点

  • 系统可用性降低:系统引入的外部依赖越多,越容易挂掉
  • 系统复杂性提高:加入了消息队列之后,要考虑很多方面的问题,比如:一致性问题、如何保证这个消息不被重复消费、如何保证消息的可靠性传输等
  • 一致性问题:如果A系统处理完了直接返回,人们都以为处理好了,但要是BCD三个系统里BC写入数库成功了,但是C写入数据库失败了,这是数据就不一致了

中间件

什么是中间件

中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台和运行平台),但在这组中间件中必须要有一个通信中间件,即中间件+平台+通信,这个定义也限定了只有用于分布式系统中才能称为中间件,同时还可以把它与支撑软件和使用软件区分开来。

为什么需要使用消息中间件

具体地说,中间件屏蔽了底层操作系统的复杂性,使程序开发人员面对一个简单而统一的开发环境,减少程序设计的复杂性,将注意力集中在自己的业务上,不必再为程序在不同系统软件上的移植而重复工作,从而大大减少了技术上的负担,中间件带给应用系统的,不只是开发的简便、开发周期的缩短,也减少了系统的维护、运行和管理的工作量,还减少了计算机总体费用的投入。

中间件的特点

为解决分布异构问题,人们提出了中间件(middleware)的概念。中间件位于平台(硬件和操作系统)和应用之间的通用服务,如下图所示,这些服务具有标准的程序接口和协议。针对不同的操作系统和硬件平台,它们可以有符合接口的协议规范的多种实现。

也很难给中间件一个严格的定义,但中间件应具有如下的一些特点:

  • (1)满足大量应用的需要
  • (2)运行于多种硬件和 OS平台
  • (3)支持分布计算,提供跨网络、硬件和 OS平台的透明性的应用或服务的交互
  • (4)支持标准的协议
  • (5)支持标准的接口

消息中间件的本质及设计

它是一种接受数据、接受请求、存储数据、发送数据等功能的技术服务
MQ消息队列:负责数据的传接受,存储和传递,所以性能要高于普通服务和技术
消息中间件的核心组成部分

  • 消息的协议
  • 消息的持久化机制
  • 消息的分发策略
  • 消息的高可用,高可靠
  • 消息的容错机制

RabbitMQ

RabbitMQ是什么

简而言之RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件,简而言之就是消息中间件
RabbitMQ服务器使用Erlang语言编写的

RabbitMQ的特点

  • 可靠性:RabbitMQ使用一些机制来保证可靠性,例如持久化、传输确认及发布确认等
  • 灵活的路由:在消息进入队列之前,通过交换器来路由信息
  • 扩展性:多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态的扩展到集群中去
  • 支持多种协议:RabbitMQ除了支持原生的AMQP协议还支持STOMP,MQTT等多种消息中间件协议
  • 支持多用语言:RabbitMQ支持所有常用的语言

AMQP是什么?

RabbitMQ就是AMQP协议的Erlang实现,是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。

RabbitMQ如何保证消息的可靠性?

生产者到RabbitMQ:事务机制和COnfirm机制(注意事务机制和Confirm机制是互斥的,不能共存)
RabbitMQ自身:持久化、集群、普通模式、镜像模式
RabbitMQ到消费者:死信机制、消息补偿机制

RabbitMQ如何保证队列的高可用?

RabbitMQ有三种模式:单机模式、普通集群模式、镜像集群模式

  • 单机模式:就是demo级别的,一般就在本地启动了玩玩,没人生产使用单机模式
  • 普通集群模式:意思就是在多台机器上启动多个RabbitMQ实例,每个机器启动一个
  • 镜像集群模式:这种模式才是真正RabbitMQ的高可用模式,跟普通集群模式不一样的是,你创建的queue,无论元数据(元数据是指RabbitMQ的配置数据)还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,都会自动地把消息到多个实例的queue里面进行消息同步

RabbitMQ使用场景

解耦、削峰、异步

  • 同步异步的问题(串行)

串行方式:将订单信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端

public void makeOrder()
    //1.发送订单
    //2.发送短信服务
    //3.发送email服务
    //4.发送app服务

  • 并行方式 异步线程池

并行方式:将订单信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间

public void test()
    //异步
    theadpool.submit(new Callable<Object>
        //1.发送短信服务
    )
    //异步
    theadpool.submit(new Callable<Object>
        //2.
    )
    //异步
    theadpool.submit(new Callable<Object>
        //3.
    )
    //异步
    theadpool.submit(new Callable<Object>
        //4.
    )


存在问题

耦合度高
需要自己写线程池自己维护成本太高
出现了消息可能会丢失,需要你自己做消息补偿
如何保证消息的可靠性你自己写
如果服务器承载不了,你需要自己去写高可用

  • 异步消息队列的方式

好处:

  1. 完全解耦,用 MQ建立桥接
  2. 有独立的线程池和运行模型
  3. 出现了消息可能会丢失,MQ有持久化功能
  4. 如何保证消息的可靠性,死信队列和消息转移等
  5. 如果服务器承载不了,你需要自己去写高可用,HA镜像模型高可用

高内聚,低耦合

好处:

  • 完全解耦,用 MQ建立桥接
  • 有独立的线程池和运行模型
  • 出现了消息可能会丢失,MQ有持久化功能
  • 如何保证消息的可靠性,死信队列和消息转移等
  • 如果服务器承载不了,你需要自己去写高可用,HA镜像模型高可用

rabbitmq的几种工作模式

  • 简单模式

  • Work queues 工作队列模式

特点:一个生产者,多个消费者,每个消费者获取到的消息唯一。

  • 发布与订阅模式

一个生产者发送的消息会被多个消费者获取。
生产者:可以将消息发送到队列或者是交换机。
消费者:只能从队列中获取消息。
如果消息发送到没有队列绑定的交换机上,那么消息将丢失。

  • 路由模式(绑定交换机)

1、 发送消息到交换机并且要指定路由key
2、 消费者将队列绑定到交换机时需要指定路由key

  • 主体模式 topic(支持*#)

将路由键和某模式进行匹配,此时队列需要绑定在一个模式上,“#”匹配一个词或多个词,“*”只匹配一个词。

以上是关于RabbitMq的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ 中的消息会过期吗?

RabbitMQ ACK、NACK、Type、TTL、死信

SpringBoot+RabbitMQ 死信队列

RabbitMQ项目使用之死信队列

Rabbitmq消费失败死信队列

SpringBoot+RabbitMQ 死信队列