分布式异步通信模式

res 中间件 中间件类型_数据

优点:系统间解耦,并具有一定的可恢复性,支持异构系统,下游通常可并发执行,系统具备弹 性。服务解耦、流量削峰填谷等。

缺点:消息中间件存在一些瓶颈和一致性问题,对于开发来讲不直观且不易调试,有额外成本。

消息中间件概念

消息中间件就是在通信的上下游之间截断:break it,Broker 然后利用中间件解耦、异步的特性,构建弹性、可靠、稳定的系统。

异步处理、流量削峰、限流、缓冲、排队、最终一致性、消息驱动等需求的场景都可以使用消息中 间件

res 中间件 中间件类型_数据帧_02

消息中间件的选型

RabbitMQ

RabbitMQ开始是用在电信业务的可靠通信的,也是少有的几款支持AMQP协议的产品之一。

优点:

  • 1. 轻量级,快速,部署使用方便
  • 2. 支持灵活的路由配置。RabbitMQ中,在生产者和队列之间有一个交换器模块。根据配置的路由规则,生产者发送的消息可以发送到不同的队列中。路由规则很灵活,还可以自己实现。
  • 3. RabbitMQ的客户端支持大多数的编程语言。

缺点:

  • 1. 如果有大量消息堆积在队列中,性能会急剧下降
  • 2. RabbitMQ的性能在Kafka和RocketMQ中是最差的,每秒处理几万到几十万的消息。如果应 用要求高的性能,不要选择RabbitMQ,但是RabbitMQ相对的延迟确实最好的
  • 3. RabbitMQ是Erlang开发的,功能扩展和二次开发代价很高。

RocketMQ

RocketMQ是一个开源的消息队列,使用java实现。借鉴了Kafka的设计并做了很多改进。 RocketMQ主要用于有序,事务,流计算,消息推送,日志流处理,binlog分发等场景。经过了历次的 双11考验,性能,稳定性,可靠性很高。

优点:

  • RocketMQ几乎具备了消息队列应该具备的所有特性和功能。
  • java开发,阅读源代码、扩展、二次开发很方便。 对电商领域的响应延迟做了很多优化。在大多数情况下,响应在毫秒级。如果应用很关注响应时间,可以使用RocketMQ。
  • 性能比RabbitMQ高一个数量级,每秒处理几十万的消息。

缺点:

  • 跟周边系统的整合和兼容不是很好。

Kafka 

Kafka的可靠性,稳定性和功能特性基本满足大多数的应用场景。跟周边系统的兼容性是数一数二的,尤其是大数据和流计算领域,几乎所有相关的开源软件都支持 Kafka。Kafka高效,可伸缩,消息持久化。支持分区、副本和容错。

Kafka是Scala和Java开发的,对批处理和异步处理做了大量的设计,因此Kafka可以得到非常高的 性能。它的异步消息的发送和接收是三个中最好的,但是跟RocketMQ拉不开数量级,每秒处理几十万的消息。

如果是异步消息,并且开启了压缩,Kafka最终可以达到每秒处理2000w消息的级别。

缺点:

  • 但是由于是异步的和批处理的,延迟也会高,不适合电商场景。

res 中间件 中间件类型_消息队列_03

消息中间件的应用场景

一,电商秒杀案例:

系统应该如何应对高并发的读请求:

  • 使用缓存策略将请求挡在上层中的缓存中
  • 能静态化的数据尽量做到静态化
  • 加入限流(比如对短时间之内来自某一个用户,某一个IP、某个设备的重复请求做丢弃处理)

系统应该如何应对高并发的写请求:

场景: 生成订单,扣减库存,用户这些操作不经过缓存直达数据库。如果在 1s内,有 1 万个数据连接同 时到达,系统的数据库会濒临崩溃。可以使用 消息队列解决问题。

消息队列的作用:

  • 削去秒杀场景下的峰值写流量——流量削峰 

1,将秒杀请求暂存于消息队列,业务服务器响应用户“秒杀结果正在处理中。。。”,释放系统资源去 处理其它用户的请求。

2,削峰填谷,削平短暂的流量高峰,消息堆积会造成请求延迟处理,但秒杀用户对于短暂延迟有一定 容忍度。

3,秒杀商品有 1000 件,处理一次购买请求的时间是 500ms,那么总共就需要 500s 的时间。这时你 部署 10 个队列处理程序,那么秒杀请求的处理时间就是 50s,也就是说用户需要等待 50s 才可以看到 秒杀的结果,这是可以接受的。这时会并发 10 个请求到达数据库,并不会对数据库造成很大的压力。

  • 通过异步处理简化秒杀请求中的业务流程——异步处理

1,先处理主要的业务,异步处理次要的业务。如主要流程是生成订单、扣减库存;次要流程比如购买成功之后会给用户发优惠券,增加用户的积分,生成订单扣减库存在操作后将订单信息通过MQ传递出去就可以返回了,积分,优惠券发放可以异步对MQ拉取或者MQ推送数据去处理。

  • 解耦,实现秒杀系统模块之间松耦合——解耦

 1,将数据全部发送给消息队列,然后数据服务订阅这个消息队列,接收数据进行处理。不同的模块去订阅消费不同的消息队列,做到解耦。

二,B-C端数据同步案例(招聘网站...)

B端面向企业用户,C端面向求职者。B端需要获取C端的更新以更新搜索引擎和缓存;C端需要获取B端的更新以更新C端的搜索引擎与缓存.

同步方式:B端和C端通过RPC或WebService的方式发布服务,让对方来调用,以获取对方的信息。求职者每更新一次简历,就调用一次B端的服务,进行数据的同步;B端企业用户每更新职位需求,就调用C端的服务,进行数据的同步。(Feign)

异步方式:使用消息队列,B端将更新的数据发布到消息队列,C端将更新的数据发布到消息队列,B端订阅C端的消息队列,C端订阅B端的消息队列。

AMQP协议剖析

AMQP全称高级消息队列协议(Advanced Message Queuing Protocol),是一种标准,类似于 JMS,兼容JMS协议(针对JAVA的消息中间件协议)。目前RabbitMQ主流支持AMQP 0-9-1,3.8.4版本支持AMQP 1.0。

res 中间件 中间件类型_数据帧_04

res 中间件 中间件类型_消息队列_05

AMQP中的概念 :

  • Publisher:消息发送者,将消息发送到Exchange并指定RoutingKey,以便queue可以接收到指 定的消息。
  • Consumer:消息消费者,从queue获取消息,一个Consumer可以订阅多个queue以从多个 queue中接收消息。
  • Server:一个具体的MQ服务实例,也称为Broker。
  • Virtual host:虚拟主机,一个Server下可以有多个虚拟主机,用于隔离不同项目,一个Virtual host通常包含多个Exchange、Message Queue。
  • Exchange:交换器,接收Producer发送来的消息,把消息转发到对应的Message Queue中。
  • Routing key:路由键,用于指定消息路由规则(Exchange将消息路由到具体的queue中),通常需要和具体的Exchange类型、Binding的Routing key结合起来使用。
  • Bindings:指定了Exchange和Queue之间的绑定关系。Exchange根据消息的Routing key和 Binding配置(绑定关系、Binding、Routing key等)来决定把消息分派到哪些具体的queue中。这依赖于Exchange类型。
  • Message Queue:实际存储消息的容器,并把消息传递给最终的Consumer。

 AMQP 传输层架构:

AMQP是一个二进制的协议,信息被组织成数据帧,有很多类型。数据帧携带协议方法和其他信 息。所有数据帧都拥有基本相同的格式:帧头,负载,帧尾。数据帧负载的格式依赖于数据帧的类型。

AMQP 使用的数据类型:

  • Integers(数值范围1-8的十进制数字):用于表示大小,数量,限制等,整数类型无符号 的,可以在帧内不对齐。
  • Bits(统一为8个字节):用于表示开/关值。
  • Short strings:用于保存简短的文本属性,字符串个数限制为255,8个字节
  • Long strings:用于保存二进制数据块。
  • Field tables:包含键值对,字段值一般为字符串,整数等。

协议协商

AMQP客户端和服务端进行协议协商。意味着当客户端连接上之后,服务端会向客户端提出一些选 项,客户端必须能接收或修改。如果双方都认同协商的结果,继续进行连接的建立过程。协议协商是一 个很有用的技术手段,因为它可以让我们断言假设和前置条件。

在AMQP中,我们需要协商协议的一些特殊方面:

  • 1、 真实的协议和版本。服务器可能在同一个端口支持多个协议。
  • 2、 双方的加密参数和认证方式。这是功能层的一部分。
  • 3、 数据帧最大大小,通道数量以及其他操作限制。

数据帧界定

TCP/IP是流协议,没有内置的机制用于界定数据帧。

现有的协议从以下几个方面来解决:

  • 1. 每个连接发送单一数据帧。简单但是慢。
  • 2. 在流中添加帧的边界。简单,但是解析很慢。
  • 3. 计算数据帧的大小,在每个数据帧头部加上该数据帧大小。这简单,快速,AMQP的选择。