异步任务管理模块设计分享

构建模块的背景

业务发展

  1. 业务刚推出的时候,产品考虑的是如何让用户使用我们的资源,因此只要提供针对资源的基本操作(购买、续费、升级等)即可
  2. 随着互联网的发展与业务发展,用户对于资源的需求量增加,因此出现了同时购买大批量的资源,同时操作大批量资源的情况,由于响应时间较长,用户体验非常不好
  3. 业务搞活动的时候,可能出现较多客户同时购买资源的情况,对正常服务造成影响,用户体验同样较差

后台服务演进

  1. 大部分后台服务提供的接口在设计之初,主要考虑的是如何完成业务功能,对于接口性能与操作逻辑优化考虑的相对比较少
  2. 业务逻辑变更或发展,导致接口逻辑愈发复杂,模块间的网络调用次数增加,同时后台存储的数据量也逐渐增加,接口耗时随之增加
  3. 先针对单个资源的操作接口逐渐洐生出批量操作接口,以应对用户的批量操作请求
  4. 大多数批量接口实际是伪批量,后台实际逻辑基本是串行的
  5. 常规的接口性能优化,包括数据缓存、逻辑优化、网络调用采用并发处理等,虽然能在一定程度上减少接口耗时,但部分优化使得接口逻辑反而变复杂了,同时部分接口耗时依然达不到要求,随着批量处理的数量的增加,接口性能优化带来的收益愈发不明显
  6. 业务搞活动时,接口请求量暴涨,部分耗时接口的性能问题会被放大,严重时可能会耗尽服务器资源,影响正常业务流程

请求异步化的思路

什么是请求异步化

  1. 后台服务收到请求之后,不立即处理请求,而是把请求记录下来
  2. 后台服务跟调用方约定获取请求执行结果的方式
  3. 后台服务异步执行对应的请求,并记录执行结果
  4. 调用方通过轮询或其他方式获取执行结果

为什么需要异步化

  1. 网络调用需要做超时处理,调用方不可能无限期等待后台服务的响应,同时用户体验不好,异步可以使调用方即时获得响应,对此做出相应的用户提示与交互
  2. 异步执行请求的频率可以调整,对于活动时接口请求量暴涨的情形,可以降低请求的执行频率,保证主线业务正常运行
  3. 为接口性能优化带来一种新的方式,不再需要牺牲代码可维护性与扩展性来做性能优化

请求异步化会带来什么问题

  1. 调用方逻辑需要改变,原来的直接请求响应的方式需要变更为轮询的方式,若调用方较多,改造成本会相对较高
  2. 需要额外的逻辑与存储来处理对应的异步请求与响应
  3. 可能引入外部模块,系统架构复杂度上升

异步任务管理模块的引入

为什么需要做独立的模块

  1. 后台服务涉及的模块比较多,在微服务比较盛行的今天,每一类相对独立的功能都可能被封装为一个服务模块,每个模块各自实现自己的异步任务管理逻辑,改造成本较高,同时也不好维护
  2. 独立的模块可以抽象出异步任务相关的API,规范任务的处理流程,对各个调用方保持统一

模块的几种设计思路

子进程同步处理+脚本触发任务检查

子进程同步处理+脚本触发任务检查

主要流程
  1. 后台服务模块每次收到请求直接,就把请求对应处理之后,调用异步任务管理模块创建任务的接口
  2. 异步任务管理模块收到创建请求,生成任务唯一标识,把请求信息写入存储,同时fork子进程回调后台服务处理对应请求,主进程则直接返回任务标识给后台服务模块,后台服务对应将任务标识返回给调用方
  3. 子进程同步等待后台服务的处理结果,并将结果记录到存储中
  4. 调用方根据任务标识,不断从异步任务管理模块轮询处理结果
  5. 离线脚本主要用于触发任务检查,防止部分任务由于子进程创建失败或者其他原因未处理
特点
  • 请求处理及时,正常情况下可保证每个请求创建之后立即被处理
  • 无法限流,若同时产生的任务较多,可能导致异步任务管理模块所在机器资源不足,或者后台服务压力较大
  • 后台服务处理接口需要支持可重入,防止因为网络等原因导致状态不同步

脚本定时处理任务

脚本定时处理任务

主要流程
  1. 后台服务模块每次收到请求直接,就把请求对应处理之后,调用异步任务管理模块创建任务的接口
  2. 异步任务管理模块收到创建请求,生成任务唯一标识,把请求信息写入存储之后直接返回该标识给后台服务模块,后台服务对应返回给调用方
  3. 离线脚本触发异步任务管理模块进行任务处理,异步任务管理模块调用后台服务模块同步获取处理结果,并更新到存储中
  4. 调用方根据任务标识,不断从异步任务管理模块轮询处理结果
特点
  • 请求处理有一定延时,若任务较多可能导致任务堆积
  • 可以部署多个离线脚本,但是异步任务管理模块自身负载会对应上升
  • 可以限流,比如离线脚本多久执行一次,限制每次处理多少个任务等
  • 后台服务处理接口需要支持可重入,防止因为网络等原因导致状态不同步

消息队列+脚本触发任务检查

消息队列+脚本触发任务检查

主要流程
  1. 后台服务模块每次收到请求直接,就把请求对应处理之后,调用异步任务管理模块创建任务的接口
  2. 异步任务管理模块收到创建请求,生成任务唯一标识,把请求信息写入存储之后,添加一条消息到消息队列,然后返回任务标识给后台服务模块,后台服务对应返回给调用方
  3. 消息队列根据预配置的策略将消息推送至后台服务模块(此处仅考虑推送模式),后台服务模块收到消息之后对应进行处理,然后将处理结果更新至异步任务管理模块
  4. 调用方根据任务标识,不断从异步任务管理模块轮询处理结果
  5. 离线脚本主要用于触发任务检查,防止部分任务消息添加失败或者其他原因未处理
特点
  • 引入消息队列,后台服务需要在消息队列配置对应策略与接口
  • 请求处理有一定延时,取决于消息队列推送策略
  • 任务堆积的问题理论上可以通过配置合理的消息队列推送策略解决
  • 限流可以通过消息队列推送策略实现
  • 若消息队列与后台服务通信出现问题,异步任务管理模块无法及时感知,可能需要增加对账机制
  • 后台服务处理接口需要支持可重入,防止因为网络等原因导致状态不同步