一、简介
异步处理,是提升服务吞吐量的最佳方法,无论在单机请求处理中,还是分布式系统中,异步处理的思路经常被用到。
- 单机异步化:比如callback,开启多个线程去处理任务,响应处理结果。我们平时开发也经常使用这种方式。
- 微服务服务之间流程异步化:比如运营在cms上选择了一批视频id,想要查询这批视频的信息,因为需要聚合大量信息,查询时间过长,让运营等待是很久是一个很差的体验。异步化处理的方式就是运营提交id列表后,可以继续去其他运营操作,等到系统查询完成后,通知用户去看结果。
归根结底,异步处理为什么可以提升性能?主要是因为异步处理可以使被动变主动。更好的调度资源,让系统拥有统一调控的能力。
二、异步设计
- push 模式:将任务派发给下游处理,因为对下游状态是无感知的避免压垮下游(当然也有池子化的,例如线程池,协程池),所以做好限流。当然任务派发者也可以主动感知下游的状态,但是会增加系统的复杂度。
- pull 模式:下游主动去获取任务,相对于push,可以根据自身情况去主动承担更多的任务处理,但是缺少调度能力。
push、pull各有各的优势,但是在我们的异步设计中,其实push与pull都是结合使用的。由分发器做好调度将任务推送到队列,handle主动去队列中拉取任务处理。例如下面这种结构。
根据以上设计我们分别实现单机异步处理与服务间异步处理设计。
二、单机异步
设计一个通用的http并发请求数据,异步处理response。具体实现直接在注释中标记。
1 | package Asynchttp |
以上就是一个通用的http并发请求,异步处理的组件。这里receive中是单协程处理response的。也可以在新建协程去处理。
测试一下
1 | package Asynchttp |
三、服务间异步化
比如观看视频,并且关注了作者,此时需要存储关注列表+1,这是一个同步过程,接着这种关注动作需要记录流水,可能还需要同步推荐测,甚至直接跟活动挂钩,关注了指定用户,同步给活动系统发放奖品等等。如果这一系列的动作都是一个同步的过程,想想都知道体验会很差。
回到最开始的模式,我们可以并发的去请求这些系统,通知他们这个关注动作,也就是push模式,这些系统也可以遍历用户关注列表,增加了就触发相关逻辑,也就是pull模式。相对来看,都不是一个很好的方案。
看下push与pull结合的方案,实线为同步过程,虚线为异步。
观看视频,修改存储后,直接向消息队列中发布消息(比如kafka),后面的推荐系统,活动系统等,直接订阅消息根据自身能力主动去处理数据就可以了。
四、异步化的问题
异步处理可以理解是将强一致性转变为最终一致性,整改异步处理的过程可能出现,消息丢失的问题,通知出现问题,handle处理失败等等。
- 消息丢失:并非所有的业务都需要100%消息不丢失的。如果想要保证数据不丢失,需要记录流水,按天来做对账。
- handle处理失败:可以选择重试,也可以选择重新消费。比如使用kafka,重置offset位置。要做好幂等设计。
具体可以看下:容错设计:补偿事务
五、总结
异步处理是提升性能和体验的有效手段,本质上因为异步处理可以使被动变主动,更好的调度资源,让系统拥有统一调控的能力。异步处理也是把强一致性转换为最终一致性的处理手段。