隔离|异步任务处理系统,如何解决业务长耗时、高并发难题?( 五 )



自适应下游处理能力的任务分发 函数计算的任务分发采用了推模式 , 这样用户只需要专注于任务处理逻辑的开发 , 平台和用户的边界也很清晰 。 在推模式中 , 有一个任务分配器的角色 , 负责从任务队列拉取任务并分配到下游的任务处理实例上 。 任务分配器要能根据下游处理能力 , 自适应的调整任务分发速度 。 当用户的队列产生积压时 , 我们希望不断增加 dispatch worker pool 的任务分发能力;当达到下游处理能力的上限后 , worker pool 要能感知到该状态 , 保持相对稳定的分发速度;当任务处理完毕后 , work pool 要缩容 , 将分发能力释放给其他任务处理函数 。

在实践中 , 我们借鉴了 tcp 拥塞控制算法的思想 , 对 worker pool 的扩缩容采取 AIMD 算法(Additive Increase Multiplicative Decrease , 和性增长 , 乘性降低) 。 当用户短时间内提交大量任务时 , 分配器不会立即向下游发送大量任务 , 而是按照“和性增长”策略 , 线性增加分发速度 , 避免对下游服务的冲击 。 当收到下游服务的流控错误后 , 采用“乘性减少”的策略来 , 按照一定的比例来缩容 worker pool 。 其中流控错误需要满足错误率和错误数的阈值后才触发缩容 , 避免 worker pool 的频繁扩缩容 。
向上游的任务生产方发送背压(back pressure) 如果任务的处理能力长期落后于任务的生产能力 , 队列中积压的任务会越来越多 , 虽然可以使用多个队列并进行流量路由来减小租户之间的相互影响 。 但任务积压超过一定阈值后 , 应当更积极的向上游的任务生产方反馈这种压力 , 例如开始流控任务提交的请求 。 在多租共享资源的场景下 , 背压的实施会更加有挑战 。 例如A , B应用共享任务分发系统的资源 , 如果A应用的任务积压 , 如何做到:
公平 。 尽可能流控A而不是B应用 。 流控本质是一个概率问题 , 为每一个对象计算流控概率 , 概率越准确 , 流控越公平 。及时 。 背压要传递到系统最外层 , 例如在任务提交时就对A应用流控 , 这样对系统的冲击最小 。如何在多租场景中识别到需要流控的对象很有挑战 , 我们在实践中借鉴了Sample and Hold算法 , 取得了较好的效果 。 感兴趣的读者可以参考相关论文 。
异步任务处理系统的能力分层 根据前述对异步任务处理系统的架构和功能的分析 , 我们将异步任务处理系统的能力分为以下三层:
Level 1:一般需 1-5 人研发团队 , 系统是通过整合 K8s 和消息队列等开源软件/云服务的能力搭建的 。 系统的能力受限于依赖的开源软件/云服务 , 难以根据业务需求进行定制 。 资源的使用偏静态 , 不具备资源伸缩 , 负载均衡的能力 。 能够承载的业务规模有限 , 随着业务规模和复杂度增长 , 系统开发和维护的代价会迅速增加 。Level 2:一般需 5-10人研发团队 , 在开源软件/云服务的基础之上 , 具备一定的自主研发能力 , 满足常见的业务需求 。 不具备完整的任务优先级、隔离、流控的能力 , 通常是为不同的业务方配置不同的队列和计算资源 。 资源的管理比较粗放 , 缺少实时资源伸缩和容量管理能力 。 系统缺乏可扩展性 , 资源精细化管理能力 , 难以支撑大规模复杂业务场景 。Level 3:一般需 10+ 人研发团队 , 能够打造平台级的系统 。 具备支撑大规模 , 复杂业务场景的能力 。 采用共享资源池 , 在任务调度 , 隔离流控 , 负载均衡 , 资源伸缩等方面能力完备 。 平台和用户界限清晰 , 业务方只需要专注于任务处理逻辑的开发 。 具备完整的可观测能力 。
结论 异步任务是构建弹性、高可用 , 响应迅速应用的重要手段 。 本文对异步任务的适用场景和收益进行了介绍 , 并讨论了典型异步任务系统的架构、功能和工程实践 。 要实现一个能够满足多种业务场景需求 , 弹性可扩展的异步任务处理平台具有较高的复杂度 。 而阿里云函数计算 FC 为用户提供了开箱即用的 , 接近于Level ?3能力的异步任务处理服务 。 用户只需要创建任务处理函数 , 通过控制台 , 命令行工具 , API/SDK , 事件触发等多种方式提交任务 , 就可以弹性、可靠、可观测完备的方式处理任务 。 函数计算异步任务覆盖任务处理时长从毫秒到24小时的场景 , 被阿里云数据库自制服务 DAS , 支付宝小程序压测平台 , 网易云音乐 , 新东方 , 分众传媒 , 米连等集团内外客户广泛应用 。
附录