在微服务的架构范式中由多个微应用构成,而服务间通信和执行流程是分布式系统的基础, 服务间的交互模式一般有3种模式:同步调用模式、接口异步调用模式、消息队列异步模式。因此我们不得不在根据业务场景进行决策,但每种交互模式意味着存在都超时的可能性,因此需要系统化的处理以满足我们系统的健壮性、容错性。
本节主要针对热门话题“微服务同步 & 异步 & 超时 & 补偿 & 快速失败”进行解说,你理解对了吗?
同步与异步
一些互联网公司试图通过规范来约束这三种方式的使用和选择:
- 尽量使用异步来替换同步操作
- 能用同步解决的问题,不要引入异步
从字面意义上看是完全不同的,甚至是矛盾的!
第 1 条原则是从业务功能的角度出发的,也就是从与用户或者使用方的交互模式出发的,如果业务逻辑允许,用户对产品的交互形态没有异议,则我们可以将一些耗时较长的、用户对响应没有特别要求的操作异步化,以此来减少核心链路的层级,释放系统的压力。
第 2 条原则是从技术和架构的角度出发的,这条原则应用的前提是同步能够解决问题, 这隐含了一个含义:如果性能不是问题,或者所处理的操作是短小的轻量级处理逻辑,那么同步调用方式是最理想不过的,因为这样不需要引入异步化的复杂处理流程。
所有 JDBC 的实现使用同步阻塞模型,即访问数据库操作时无论是查询还是更新,原则上都是短小操作,不需要异步化。
交互模式
同步调用模式 | 同步调用模式适用于大规模、高并发的短小操作, 不适用于后端负载较高的场景 |
接口异步调用模式 | 适用于非核心链路上负载较高的处理环节,这个环节经常耗时较长,并且对时效性要求不高 |
消息队列异步模式 | 消息队列异步处理模式与接口异步调用模式类似,多应用于非核心链路上负载较高的处理环节中 解耦 流量具有消峰 |
超时问题的解决方案
同步调用模式 | 服务契约中规定三种处理结果,状态值为:成功、失败和处理中,对于超时等系统错误的请求,其实可以认为是处理中状态的一个特例,可采用超时补偿的原则的方式 |
接口异步调用模式 | 不需要三种状态,尽最大努力通知即可 |
消息队列异步模式 | 有2个阶段:生产者投递和消费者处理, 在每个阶段会产生超时问题 1.生产者投递超时,基本上可以视为失败(不可以不常见) 2.消息队列的消费超时,一般消息队列会提供两种方式来消费消息
|
超时补偿的原则
服务间同步超时造成的后果进行处理,而处理方法有快速失败和内部补偿两种,补偿模式也有调用方补偿和接收方补偿两种。
快速失败:补偿模式有一种叫取消操作,主动触发即可。
服务A调用服务B ,如果服务B响应服务A并且告诉服务A 消息己接收,那么服务A的任务就结束了;如果服务B处理失败,那么服务 B应该负责重试或者补偿。
服务A调用服务B ,如果服务B 没有给出明确的接收响应,例如网络超时,那么服务A应该持续进行重试,直到服务B明确表示己经接收消息。 在这种情况下容易出现重复的消息,因此在服务 B中通常要保证滤重或者幕等性。
如果你对不一致问题还存在疑问可参阅我之前的分享微服务最终一致性。