RabbitMQ的引入、使用业务场景、优势、工作机制

RabbitMQ介绍及使用场景、优势

  MQ全称为message queue,即消息队列,又叫消息中间件。RabbitMQ是由erlang语言开发,基于AMQP(advanced message queue 高级消息队列协议)协议实现的消息队列,这是一种程序之间通信方法。通过高效可靠的消息传递机制进行与平台无关的数据交流.基于数据通信来进行分布式系统的集成,通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信.消息队列在分布式系统开发中应用非常广泛.
  RabbitMQ官方地址

使用RabbitMQ的业务场景

1.服务间异步处理:可进行异步处理的业务(姐姐了不需要同步处理,且耗时长、消息接收方可以异步处理的业务问题)
  同步通信:发出一个请求后,没有得到结果前不返回结果,调用者主动等待这个结果。
  异步通信:调用者发出请求后,调用直接返回,没有返回结果。也就是说,一个异步过程调用发出后,调用者不会马上得到结果。而是在调用发出后,被调用者通过状态通知调用者,或者通过回调接口函数等处理这个调用。

2.对没有依赖的业务进行解耦(例如退货后,需要回复库存、资金退还,发送通知可以使这些业务之间没有相应的依赖关系)
  耦合使系统内部或者系统之间存在的相互作用,相互影响和相互依赖。在我们的分布式系统中,一个业务流程涉及多个系统的时候,他们之间会形成一个依赖关系。
  例如:在传统通信方式中,订单系统发生退火车票,那么要调用所有下游系统的api,比如调用库存系统的api回复库存,因为这张火车票还要释放给其他乘客购买;调用支付系统api接口,不论是支付宝微信还是银行卡,要把手续费扣除以后,原路退回给消费者;调用通知系统api通知用户退票成功。
  上诉整个过程是串行执行,如果在回复库存的时候发生了异常,那么后面的代码都不会执行。由于一系列操作,恢复库存,资金退还,发送通知,没有严格的先后顺序,也没有直接依赖关系,都是独立的系统。
  解决方案1:多线程
  使用多线程或者线程池可以实现,但是每个并行执行的地方都引入线程,又会带来线程或线程池的管理问题。
  解决方案2:使用mq
  使用mq订单系统需要把退货的消息发送到消息队列上,由各个下游业务系统自己创建队列,然后监听队列消费消息。这种情况下订单系统里不需要配置其他系统的ip、端口、接口地址了,因为它不需要关心消费者在网络上什么位置,所以下游系统改ip没有任何影响,甚至不需要关心消费者有没有消费成功,它只需要把消息发送到消息队列服务器上即可,这样,我们就实现了系统之间依赖关系的解耦。

3.实现流量削峰
  很多电商系统里,会有瞬间流量达到峰值情况,比如双十一,618等活动,普通的硬件服务器肯定支撑不了这种百万或者千万级别的并发量。如果通过堆硬件方式解决,那么流量峰值过去后悔出现巨大的资源浪费。
  基于以上背景,为了保护我们的数据库和服务器,限流也是可以的,但是会导致订单丢失,用户体验不佳,没有达到目的,引入mq队列,先进先出就可以把所有的流量承接下来,转换成mq消息发送到消息队列服务器上,业务层可以根据自己的消费速率处理这些消息,处理之后再返回结果。

4.消息通讯
  
消息队列一般都内置了高效的通信机制,因此也可以用在纯消息通讯,比如点对点消息队列,聊天室等。
5.顺序消费
6.定时任务

总结:

  1.数据量大或耗时长的操作,mq实现异步通信,减少客户端等待,提升响应速度。
  2.对于改动影响大的系统,mq实现解耦,减少系统之间直接依赖(如:订单取消后增加库存、退还支付金额、发送消息通知)。
  3.对于瞬间的流量峰值系统,mq实现流量削峰,达到保护应用和数据库的目的(如:商品抢购预定)。

市场上还有那些消息队列,为什么使用rabbitmq?

ActiveMq、RabbitMq、ZeroMq、Kafka、MetaMq、RocketMq、Redis

1、使用简单、功能强大
2、基于amqp协议:除了qpid,rabbitmq是唯一一个实现amqp标准的消息服务器;
3、可靠性:Rabbitmq的持久化,保证消息稳定性;
4、集群部署简单:因为erlang使rabbitmq集群部署变得很简单;
5、社区活跃、文档完善,rabbitmq也是首选;
6、高并发性能好,rabbitmq使用erlang语言开发,erlang是电话交换机开发的语言,自带高并发和高可用特性;
7、springboot默认已集成rabbitmq;

RabbitMQ的工作机制

RabbitMQ的概念

1、Broker(代理、中间件,这里指消息队列服务器):进程包括两部分Exchange和Queue
  a、Exchange:消息队列交换机,按一定规则将消息路由转发到某个队列,对消息进行过滤。队列使用绑定键(Binding Key)跟交换机建立绑定关系。
  b、Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方,它是消息容器,也是消息终点。一个消息可投入一个或多个队列。消息一直在队列里,等待消费者连接到这个队列将其取走。
2、Producer(消息生产者):生产方客户端,生产方客户端将消息发送到mq。
3、Consumer(消息消费者):消费方客户端,接收mq转发的消息。
4、Message(消息):由消息头和消息体组成,消息体是不透明的,消息头由一些列的可选属性组成,这些属性包括routing-key(路由键)、priority(优先权)、delivery-mode(消息可能需要持久性存储)等。
5、Bingding(绑定):用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成由绑定构成的路由表。
6、Connection(连接):无论生产者发送消息,还是消费者接收消息,都必须跟Broker之间建立一个连接,这个是tcp长链接。
7、Channel(信道):多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的tcp连接内的虚拟连接数,amqp命令都是通过信道发送出去的,不管是发布消息,订阅队列还是接收消息,这些动作都是通过信道完成的。因为对于操作系统来说建立和销毁tcp都是非常昂贵的开销,所以引入了信道的概念。
  信道是建立在连接基础上,实际开发中连接应为全局变量,信道为线程级。一个连接可以创建多个信道【采用多线程】;一个应用或者一个线程都是一个信道,在信道中,创建队列queue。生产者的信道一般会立马关闭,消费者由于一直监听,信道几乎是一直存在。
8、virtual host:虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器。
  每个rabbit都能创建很多vhost,我们称之为虚拟主机,每个虚拟主机都是mini版的rabbit mq,拥有自己的队列,交换器和绑定,拥有自己的权限机制。vhost是amqp概念的基础,必须在连接时指定,每一个rabbitmq服务器都有一个默认的虚拟主机“/”,rabbitmq server可以说就是消息队列服务器实体(broker),broker当中可以有很多个用户,而用户只能在虚拟主机的粒度进行权限控制,所以rabbitmq中需要多个虚拟主机。vhost特性如下:
  a、rabbit mq默认的vhost是“/”开箱即用;
  b、多个vhost是隔离的,多个vhost无法通讯,并且不用担心命名冲突(队列、交换器、绑定),实现了多层分离。

RabbitMQ消息创建、订阅、消费过程原理

  创建tcp连接 --> tcp连接认证并创建信道 --> 消息投递到交换器 --> 交换机转发到具体队列 --> 队列将消息以推送或者拉取方式给消费者进行消费
  1、应用程序和rabbit server之间会创建一个tcp连接,一旦tcp打开,并通过了认证(认证就是你试图连接rabbit之前发送的rabbit服务器连接信息和用户名密码,有点像程序连接数据库),应用程序就rabbit创建了一条amqp信道,该信道是创建在“真实“tcp”上的虚拟连接,amqp命令都是通过信道发送出去的,每个信道都有唯一id,不论是发布消息,订阅队列或者接收消息都是通过信道来完成的。
  2、生产者发送消息不会像传统方式直接将消息投递到队列中,而是将消息投递到交换器中,再由交换器转发到具体的队列,队列再将消息以推送或者拉取方式给消费者进行消费。交换器作用根据具体的路由策略分发到不同队列。(这就是交换器的作用)

为什么不通过tcp直接发送命令

  对于操作系统来说创建和销毁tcp会话是非常昂贵的开销,假设高峰期每有成千上万条连接,每一个连接都要创建一条tcp会话,就会造成tcp连接的巨大浪费,并且操作系统每秒能创建的tcp也是有限的,很快会遇到系统瓶颈。
  如果我们每个请求都是用一条tcp连接,即满足的性能需求,又能保证每个连接的私密性,这就是引入信道的原因。

erlong9.3与rabbitmq 3.7.5中常用命令

1、安装、启动、停止rabbitmq命令:

##安装服务
rabbitmq-service.bat install
##停止服务
rabbitmq-service.bat stop
##启动服务
rabbitmq-service.bat start    
View Code

2、对虚拟主机的相关命令操作:

##通过rabbitmqctl工具命令创建
rabbitmqctl add_vhost[vhost_name]
##删除vhost
rabbitmqctl delete_vhost[vhost_name]
##查看所有的vhost
rabbitmqctl list_vhosts
View Code

重复消费是如何产生的?

正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除;但是因为网络传输等故障,确认消息没有传送到消息队列,导致消息队列不知道该消息被消费,会再次将消息分发给其他消费者或者向同一个消费者发送两条同样的消息记录。

重复消费如何解决?

1、确保消息唯一性,即使多次传输,不要让消息的多次消费带来影响,保证消费消息是幂等的;
2、在写入消息队列的数据做唯一标识,消费消息时,根据唯一标识在消费日志表中判断是否被消费过;

读书犯困,因为那是梦开始的地方;
原文地址:https://www.cnblogs.com/AlanWilliamWalker/p/14692695.html