分布式消息中间件(rabbitMQ篇)

  笔者去年刚醒悟(觉得自己太菜)的时候,实在不知道从上面学起,偶然看到厮大的RabbitMQ的文章觉得,rabbitMQ很强大,刚好也是中间件,大部分场景都用得到,所以就从中间件下手了。

     

  1.     RabbitMQ是使用最广泛的消息代理之一

名词概念

  • Message

    消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。

  • Publisher

    消息的生产者,也是一个向交换器发布消息的客户端应用程序。

  • Exchange

    交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。

  • Binding

    绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。

  • Queue

    消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。

  • Connection

    网络连接,比如一个TCP连接。

  • Channel

    信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。

  • Consumer

    消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。

  • Virtual Host

    虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是 / 。

  • Broker

    表示消息队列服务器实体。

2..消息队列解决了什么问题?

异步处理 (节省大量时间)

应用解耦 (MQ作为两个系统的连接点)

流量消锋 (使用MQ过滤掉一些请求,达到请求消减)

日志处理(kafka在这方面比较强大)

这是MQ中最经典的模式点对点,一个消息的发布者,一个消息的订阅者,中见红色的为队列

不足之处:耦合性高,生产者一一对应消费者。多个消费者无法同时消费队列中的消息

队列名字变更,对应的P和C 也要进行修改

于是就出现了Work Queues(工作队列) 模型

Simple 队列 是一一对应的,而且实际开发中 发消息的时间非常短的,但是根据实际业务的需求,消费者处理消息是需要时间的。如果消息的提供者一直等着一个消费者处理完一个消息后,在处理另一个消息,这种是比较耗费效率的。

 

出现多个消费者的方式,MQ使用了轮询分发(round-robin)

就是 任务是平均分配的,不会说某个消费者处理的块,就多发给它一个消息。

上面的分配方法,虽然解决了一点压力,但是对系统的压力还是比较大的。处理块的消费者处理完之后就不处理队列了,导致了资源浪费,这时候用以下的方式就行优化。

 

公平分发(即为消费者处理完后,自己确认已处理队列,并像队列要新的消息)

要求,必须关闭自动确认消息,需要手动确认消息

消息应答机制(默认为false)

将消息的应答机制改为false,表示不自动应答。(这个在集成spring 的时候可以做到消息在消费者消费完成之后,手动应答可以保证消息不会再消费端丢失,但是要注意消费端的幂等性)

核心代码为3个参数里面中间的那个参数,

为ture就是自动应答,

自动应答风险,一旦MQ将消息发送出去后,就会从内存在删除这条消息,如果这时消费者在消费的时候突然宕机了,对应的消息就会消失,存在一定的风险。

为false就是手动应答。

手动应答相比于自动应答优点在于,消息处理完成后需要消费者手动确认,此条消息处理完毕,内存中就会删除。当消费者宕机的时候,MQ会自动的发一条消息,给其它消费者。这样就避免了消息的丢失。

持久化机制(已声明的队列,无法修改是否持久化.如果想使用持久化,必须删除队列,重新声明,持久化的队列信息,放在MQ安装目录下,具体哪个地方不知道。)

出现原因,当mq服务器宕机了,我们要避免在服务器中的消息丢失,就要把我们的消息,存入到数据库中。等Mq再次重启的时候,就从数据库中读取未处理的消息.

RabbitMQ推荐的方式,订阅模式(publish/subscribe),必须要先创建一个交换机(,先创建消息的提供者)

1.一个生产者,多个消费者

2.每一个消费者都有自己的队列。

3.生产者不把消息直接发送到队列,而是把消息发送到交换机中

4.每个队列都绑定了交换机

5.生产者发送消息经过交换机,到达队列,实现一个消息被多个消费者消费。

这个模型的原理也是Rabbit的工作原理,消息的提供者先将消息发送到交换机里面,这个交换机必须是提前声明的,否则消息会丢失。我们在创建交换机的时候需要绑定RoutingKey,而消费者在消费消息的时候也是通过队列绑定routingkey进行消费的。这样也就起到了松耦合的作用,上游不知道消息被谁消费,只管将消息发送到Broker中即可,下游也不需要指定是谁发的消息,只需要对自己感兴趣的队列进行订阅即可。(下图为消息流转模型和MQ消费原理)

 

上面 的图可适用于下列场景

1.注册---发邮件----短信(可以叫在注册成功后叫消息发送至一个队列,然后声明两个消费者,实现发邮件和发短信逻辑)

2.延时消费,在规定的时间内是否支付,如果超过规定时间,则认为放弃了此次订单。(可通过队列来设置延时时间)

3.异步下单,( 两个系统,一个系统下单成功,另一个系统减去库存。相当于MQ解决分布式事务案例。)

 在微服务项目中由于粒度过于细,所以我们通常会遇到涉及到两个数据源的情况,这时候我们就需要考虑分布式事务的情况了,因为spring的事务管理器无法帮我们同时管理两个数据源,这个时候有人会想说使用2pc,3pc等,这些都是可以的,使用MQ实现分布式事务是base理论中的软状态来实现最终一致性,这个我后续也会写一篇博客

4.流量削锋(消费的时候采取拉的模式,自己去到broker中去拉取消息然后消费,因为我们平时用得最多的模式就是订阅队列, 然后又消息来的时候直接将消息推送给对应的消费者(这也是设计模式中,观察者模式的机制实现))

上面我们也说了RabbitMQ中的通信机制是将Message发送到交换机中(Exchange)然后由Exchange来发送消息到Broker中。下面我们来讲一下MQ中的交换机。

Rabbit中的交换机主要分为4种

  • direct(默认)
  • headers
  • fanout
  • topic

fanout交换机相当于路由的意思。大致结构如下

Fanout (不处理路由键,只要有消息就发送给所有消费者(监听fanout交换机的队列,可以理解为广播)

使用场景可以对个队列绑定同一交换机,当次交换机有消息推送的时候,每个不同的队列,各自处理各自的业务逻辑。

Direct(处理路由键,指定单个消费者,进行消息处理)

使用场景,使用单独的路由key来指定唯一的一个的消费者。比如pro.add,pro.update(每个路由key处理各自的逻辑)

图中的error,info,warning等消息,都是路由key

Topic Exchange(主题)模式 路由模式的升级版

tt.add  消费者的key为tt.*的时候可以匹配

tt.add  消费者的ket为tt.#可以全部匹配

"*"匹配一个分段(用“.”分割)的内容;

"#"匹配0和多个字符;

使用场景相当于是direct升级版,前者是单个匹配,后者是模糊匹配。使用的时候感觉差的不是太多。

 

消息如何保证100%保证投递成功。

1.保证消息的成功发出

2.保证MQ节点成功接收

3.发送端收到MQ确认,确认到达

4.落库和完善的补偿机制(消息落库,对消息状态进行标记,消息的延迟投递,做二次确认回调检查)

此场景适用于银行等系统,因为入库两次对性能有影响,但是对消息的到达起了一定的作用

上图中的最终解决方案就是开发人员读日志,然后确认并解决问题,上面的所有步骤异常都会存入日志中。读日志的时候可以通过elk+kafka的形式来实现写入快速性和读的可视化。后续我也会说明elk如何搭建。

上图中可以优化的点就是把两次写入MSG的操作改成一次,写入的时候在4步之后执行,如果消息成功到达,那么将此条消息,写入库,这样定时任务,就可以改为查询是否有那条记录,可通过记录id,定时任务开启的时间可以在第一步中消息的唯一id生成之后开始执行。如果没id就说明没写入成功继续执行补偿逻辑。

MQ架构

 

上面的架构可以解决以下问题:

1.支持消息高性能的序列化转换器,异步发送消息

2.支持消息生产者实例与消费实例,缓存化提升性能

3.支持可靠性消息投递,消息不丢失

4.支付消费端幂等性操作,避免消费端重复消费。

5.支持迅速发送消息,在一些日志场景使用

6.支持延迟消息发送

7.支持事务。

  ---------本文知识储备来自于蚂蚁课堂,感谢余总的指点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值