shenzhenzsw 2020-06-21
1、mq的应用场景:
1) 对于数据量大或者处理耗时长的操作,我们可以引入 MQ 实现异步通信,减少客户端的等待,提升响应速度。
2) 对于改动影响大的系统之间,可以引入 MQ 实现解耦,减少系统之间的直接依赖。
3) 对于会出现瞬间的流量峰值的系统,我们可以引入 MQ 实现流量削峰,达到保护应用和数据库的目的
2、使用消息队列带来的问题:
1)系统可用性降低:原来是两个节点的通信,现在还需要独立运行一个服务,如果 MQ 服务器或者通信网络出现问题,就会导致请求失败。
2)系统复杂性提高: 为什么说复杂?
第一个就是你必须要理解相关的模型和概念,才能正确地配置和使用 MQ。
第二个,使用 MQ 发送消息必须要考虑消息丢失和消息重复消费的问题。一旦消息没有被正确地消费,就会带来数据一致性的问题
3、rabbitmq简介:
3-1、基本特性:
1)高可靠:RabbitMQ 提供了多种多样的特性让你在可靠性和性能之间做出权衡,包括持久化、发送应答、发布确认以及高可用性。
2)灵活的路由:通过交换机(Exchange)实现消息的灵活路由。
3)支持多客户端:对主流开发语言(Python、Java、Ruby、PHP、C#、JavaScript、 Go、Elixir、Objective-C、Swift 等)都有客户端实现。
4)集群与扩展性:多个节点组成一个逻辑的服务器,支持负载。
5)高可用队列:通过镜像队列实现队列中数据的复制。
6)权限管理:通过用户与虚拟机实现权限管理。
7)插件系统:支持各种丰富的插件扩展,同时也支持自定义插件。
8)与 Spring 集成:Spring 对 AMQP 进行了封装。
3-2、AMQP协议
AMQP:高级消息队列协议,是一个工作于应用层的协议
除了 RabbitMQ 之外,AMQP 的实现还有 OpenAMQ、Apache Qpid、RedhatEnterprise MRG、AMQP Infrastructure、ØMQ、Zyre。
除了 AMQP 之外,RabbitMQ 支持多种协议,STOMP、MQTT、HTTP and WebSockets。
可以使用 WireShark 等工具对 RabbitMQ 通信的 AMQP 协议进行抓包。
3-2rabbitmq的工作模型
1)、Broker:RabbitMQ 的服务,默认是 5672 的端口。中文翻译是代理/中介,MQ 服务器帮助我们做的事情就是存储、转发消息。
2)、Connection:无论是生产者发送消息,还是消费者接收消息,都必须要跟 Broker 之间建立一个连接,这个连接是一个TCP 的长连接。
3)、Channel:如果所有的生产者发送消息和消费者接收消息,都直接创建和释放 TCP 长连接的话,对于 Broker 来说肯定会造成很大的性能损耗,因为 TCP 连接是非常宝贵的资源,创建和释放也要消耗时间。所以在 AMQP 里面引入了 Channel 的概念,它是一个虚拟的连接。我们把它翻译成通道,或者消息信道。这样我们就可以在保持的 TCP 长连接里面去创建和释放Channel,大大了减少了资源消耗。另外一个需要注意的是,Channel 是 RabbitMQ 原生 API 里面的最重要的编程接口,也就是说我们定义交换机、队列、绑定关系,发送消息消费消息,调用的都是 Channel 接口上的方法。
4)、Queue:队列是真正用来存储消息的,是一个独立运行的进程,有自己的数据库(Mnesia)。
消费者获取消息有两种模式:
一种是 Push 模式,只要生产者发到服务器,就马上推送给消费者。
另一种是 Pull 模式,消息存放在服务端,只有消费者主动获取才能拿到消息
我们可以基于事件机制,实现消费者对队列的监听,由于队列有 FIFO 的特性,只有确定前一条消息被消费者接收之后,才会把这条消息从数据库删除,继续投递下一条消息。
5)、Exchange:在RabbitMQ 里面永远不会出现消息直接发送到队列的情况。因为在 AMQP 里面引入了交换机(Exchange)的概念,用来实现消息的灵活路由。
交换机是一个绑定列表,用来查找匹配的绑定关系。队列使用绑定键(Binding Key)跟交换机建立绑定关系。生产者发送的消息需要携带路由键(Routing Key),交换机收到消息时会根据它保存的绑定列表,决定将消息路由到哪些与它绑定的队列上。
注意:交换机与队列、队列与消费者都是多对多的关系。
6)、Vhost:VHOST 可以提高硬件资源的利用率,还可以实现资源的隔离和权限的控制。它的作用类似于编程语言中的 namespace 和 package,不同的 VHOST 中可以有同名的 Exchange 和 Queue,它们是完全透明的。
如果某个业务系统不想跟别人混用一个系统,怎么办?
这个时候,我们可以为不同的业务系统创建不同的用户(User),然后给这些用户分配 VHOST 的权限。比如给风控系统的用户分配风控系统的 VHOST 的权限,这个用户可以访问里面的交换机和队列。给超级管理员分配所有 VHOST 的权限。
7)、消息的路由方式:
(1)直连(Direct):队列与直连类型的交换机绑定,需指定一个精确的绑定键。生产者发送消息时会携带一个路由键。只有当路由键与其中的某个绑定键完全匹配
时,这条消息才会从交换机路由到满足路由关系的此队列上。
例 如 : channel.basicPublish(“MY_DIRECT_EXCHANGE”,”spring”,”msg1”); 只有第一个队列能收到消息
(2)主题(topic):
解读:第一个队列支持路由键以 excel 开头的消息路由,后面可以有单词,也可以没有。
第二个队列支持路由键以 word开头,并且后面是一个单词的消息路由。
第三个队列支持路由键以 ppt结尾,并且前面是一个单词的消息路由。
例如:
channel.basicPublish("MY_TOPIC_EXCHANGE","excel .fjd.klj","msg 2"); 只有第一个队列能收到消息。
channel.basicPublish("MY_TOPIC_EXCHANGE","excel.ppt", "msg 3"); 第一个队列和第三个队列能收到消息。
(3)广播(fanout):
主题类型的交换机与队列绑定时,不需要指定绑定键。因此生产者发送消息到广播类型的交换机上,也不需要携带路由键。消息达到交换机时,所有与之绑定了的队列,
都会收到相同的消息的副本。
例如:channel.basicPublish("MY_FANOUT_EXCHANGE", "", "msg 4"); 三个队列都会收到 msg4。