同步通讯/异步通讯
微服务间通讯有同步和异步
两种方式
同步通讯
: 类似打电话场景需要实时响应(时效性强可以立即得到结果方便使用),而且通话期间不能响应其他的电话(不支持多线操作)异步通讯
: 类似发邮件场景不需要马上回复并且可以多线操作(适合高并发场景)但是时效性弱响应会有延迟
同步通讯的缺点
微服务间基于Feign的调用
就属于同步方式,虽然调用可以实时得到结果但是存在一些问题
耦合度高
: 每次加入或删除业务都需要去支付服务中改动原来的代码性能/吞吐能力下降
: 调用者(支付服务)需要等待服务提供者响应完成后才能执行下一步的操作,如果调用链过长则响应时间等于每次调用服务的时间之和资源浪费
: 调用者(支付服务)在等待服务提供者响应过程中啥也不干却一直占用着CPU和内存,高并发场景下会极度浪费系统资源级联失败
: 如果服务提供者(仓储服务)出现问题会导致所有的请求都卡在这里,最后随着请求越来越多支付服务也会将系统资源耗尽导致整个微服务故障
// 用户支付完成支付服务调用其他服务
public void PaymentService() {
// 调用订单服务完成订单状态修改
orderService.doSth();
// 调用物流服务从仓库分配响应的库存并准备发货
storageService.doSth();
messageService.doSth();
...
}
异步通讯
异步调用的常见实现是事件驱动模式
,如购买商品时用户支付后需要调用订单服务完成订单状态修改,调用物流服务从仓库分配响应的库存并准备发货
- 支付服务是事件发布者(publisher),在支付完成后只需要发布一个支付成功的事件(event),事件中带上订单Id
- 订单服务和物流服务是支付成功事件的订阅者(Consumer),订阅者监听到自己订阅的事件发布后就会执行对应的业务逻辑代码
Broker
: 事件发布者与订阅者之间的并不是直接通信(解耦合),发布者只负责发布事件到Broker
(不关心订阅者),订阅者负责从Broker订阅事件
(不关心发布者)
异步通讯的优点
吞吐量/性能提升
: 支付服务只需要向Broker发布一个支付成功的事件剩下的就不用它管了故障隔离
: 如果仓储服务挂掉也丝毫不会影响到支付服务,因为支付服务不需要等待仓储服务响应完成, 所以支付服务也就不会再占用无意义的系统资源流量削峰
: 不管发布事件的流量波动多大都是由Broker接收,订阅者可以按照自己的处理速度去Broker取事件处理- 添加新服务时只需要让新服务来订阅事件,删除服务时只需要让服务取消订阅事件,不需要修改支付服务的代码解除了服务之间的耦合
异步通讯的缺点
- 整个异步通讯过程中所有服务间的调用都是依赖于Broker来实现的,所以对Broker的可靠性,安全性,吞吐能力要求较高
- 异步通讯导致架构复杂,业务没有明确的流程线出了问题不方便追踪管理
相关技术
MQ(MessageQueue)中文是消息队列即存放消息(事件)的队列,也就是事件驱动模式中的Broker
- 追求可用性: Kafka、RockerMQ、RabbitMQ
- 追求可靠性: RabbitMQ、RocketMQ
- 追求吞吐能力: RocketMQ、Kafka
- 追求消息低延迟: RabbitMQ、Kafka