欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

微服务间异步调用相互通讯的方案和分析

程序员文章站 2022-07-09 19:40:30
背景公司的服务都是微服务之前的调用,现在A服务需要使用B服务的功能,但是B服务处理业务是需要一定的时间的。为了提高服务间的吞吐采用异步的方式执行。同步调用和异步调用同步调用带来的坏处同步调用需要被调用方的吞吐不低于调用方的吞吐。否则会导致被调用方因为性能不足而拖死调用方。换句话说,整个同步调用链的性能会由最慢的那个服务所决定。同步调用会导致调用方一直在等待被调用方完成,如果一层接一层地同步调用下去,所有的参与方会有相同的等待时间。这会非常消耗调用方的资源。因为调用方需要保存现场(Context...

背景

公司的服务都是微服务之前的调用,现在A服务需要使用B服务的功能,但是B服务处理业务是需要一定的时间的。为了提高服务间的吞吐采用异步的方式执行。

同步调用和异步调用

  1. 同步调用带来的坏处
    1. 同步调用需要被调用方的吞吐不低于调用方的吞吐。否则会导致被调用方因为性能不足而拖死调用方。换句话说,整个同步调用链的性能会由最慢的那个服务所决定。
    2. 同步调用会导致调用方一直在等待被调用方完成,如果一层接一层地同步调用下去,所有的参与方会有相同的等待时间。这会非常消耗调用方的资源。因为调用方需要保存现场(Context)等待远端返回,所以对于并发比较高的场景来说,这样的等待可能会极度消耗资源。
    3. 同步调用只能是一对一的,很难做到一对多。同步调用最不好的是,如果被调用方有问题,那么其调用方就会跟着出问题,于是会出现多米诺骨牌效应,故障一下就蔓延开来。
  2. 所以,异步通讯相对于同步通讯来说,除了可以增加系统的吞吐量之外,最大的一个好处是其可以让服务间的解耦更为彻底,系统的调用方和被调用方可以按照自己的速率而不是步调一致,从而可以更好地保护系统,让系统更有弹力。

异步调用的几种方式:

  • 请求响应式
  • 通过订阅的方式
  • 通过 Broker 的方式

具体方式解读:
https://time.geekbang.org/column/article/3926

项目中的应用

第一版方案

  1. 第一版方案比较原始,采用的是定时任务跑JOB的方式来主动获取异步结果(如下图)。
    微服务间异步调用相互通讯的方案和分析

  2. 遇到的问题:

    1. 这个定时任务设置的时间如何来把控(这真的很难设定)。我们使用的是根据用户每秒的上传量来进行设定的。然后根据每次处理的数据量做一个计算保证不产生数据堆积。而产生很多中间状态
    2. 还有就是这个job的时间也限制了被调用服务的吞吐了。比如我上传300条数据处理,这300条在很短时间处理完成了,而我的客户端job设置了1分钟跑一次,切每次处理100,那这就得3分钟了。所以完全限制了服务的吞吐。
    3. 还有就是如果服务来个突然猛增,那这就GG了,之前的job参数就有问题了。我们在实际情况汇总中就遇到了这个问题,导致发起回来后,

第二版方案

  1. 采用回调的方式进行交互
    微服务间异步调用相互通讯的方案和分析

  2. 回调的过程有ACK机制,当只有A服务确定收到了且成功处理了B服务的回调结果才会成功,不然B服务会有重试机制(有限次数)。

  3. 相对于定时job的优势:通过回调的方式解决了刚开始定时job方式在吞吐量方面的瓶颈,还有就是当数据量很大的时候,在进行扫描表的时候也会浪费一些时间。

  4. 实际情况遇到问题: A服务吧任务给B服务,B服务产生任务编号,直接同步返回给A服务,B服务处理完任务回调给A A是根据这个任务号进行更新的,就在这时出现问题了。
    回调的结果比taskID落库快。 这下完了,回调回来。没有这个taskID,然后迅速回调了三次都挂掉了。导致任务一直处于中间状态。

第三版方案(解决第二版方案问题)

  1. 采用延时队列,当没有这个taskID的时候放入延时队列,当落库后消费延时队列的消息。

  2. 采用定时任务,做兜底如下:
    微服务间异步调用相互通讯的方案和分析

    1. 关于扫描表时间长的问题,采用请求的时当前时间前1分钟的前1小时的数据。
    2. 真的时B服务处理没有成功没有获取到对应的taskID数据,那就直接更新为失败任务。
  3. 可以发现这是第一个方案和第二个方案的结合,但是如果我们从根源解决问题呢?出问题的原因就是在更新TaskID上,我们一方面让taskID变快,另一方面就是提早的将taskID落库。那就选择能不能把taskId生成的地方放在发起的服务上呢?
    感觉没有什么问题啊。但是总是感觉有点怪,但是并不知道是哪里怪。还请大家出出建议。

总结

  • 同步调用有四个问题:影响吞吐量、消耗系统资源、只能一对一,以及有多米诺骨牌效应。于是,我们想用异步调用来避免该问题。
  • 异步调用有三种方式:请求响应、直接订阅和中间人订阅。
  • 但是一定要注意接口幂等问题,防止数据不能保证最终一致性

本文地址:https://blog.csdn.net/weixin_40413961/article/details/107869019