网络安全|详解异步任务:函数计算的任务触发去重?

网络安全|详解异步任务:函数计算的任务触发去重?

文章图片

网络安全|详解异步任务:函数计算的任务触发去重?

文章图片


前言 无论是在大数据处理领域 , 还是在消息处理领域 , 任务系统都有一个很关键的能力 - 任务触发去重的保障 。 这个能力对于一些准确性要求极高的场景中(如金融等)是必不可少的 。 作为 Serverless 化任务处理平台 , Serverless Task 也需要提供这类保障 , 在用户应用层面及自身系统内部两个维度具备任务的准确触发语义 。 本文主要针对消息处理可靠性这一主题来介绍函数计算内部的一些技术细节 , 并展示如何在实际应用中使用函数计算所提供的这方面能力来增强任务执行的可靠性 。
浅谈任务去重 在讨论异步消息处理系统时 , 消息处理的基本语义是无法绕开的话题 。 在一个异步的消息处理系统(任务系统)中 , 一条消息的处理流程简化如下图所示:
图 1
用户下发任务 - 进入队列 - 任务处理单元监听并获取消息 - 调度到实际 worker 执行
在任务消息整个的流转过程中 , 任何组件(环节)可能出现的宕机等问题会导致消息的错误传递 。 一般的任务系统会提供至多 3 个层级的消息处理语义:
●At-Most-Once:保证消息最多被传递一次 。 当出现网络分区、系统组件宕机时 , 可能出现消息丢失;
●At-Least-Once:保证消息至少被传递一次 。 消息传递链路支持错误重试 , 利用消息重发机制保证下游一定收到上游消息 , 但是在宕机或者网络分区的场景下 , 可能导致相同消息传递多次 。
●Exactly-Once机制则可以保证消息精确被传送一次 , 精确一次并不是意味着在宕机或网络分区的场景下没有重传 , 而是重传对于接受方的状态不产生任何改变 , 与传送一次的结果一样 。 在实际生产中 , 往往是依赖重传机制接收方去重(幂等)来做到 Exactly Once 。
函数计算能够提供任务分发的 Exactly Once 语义 , 即无论在何种情况下 , 重复的任务将被系统认为是相同的触发 , 进而只进行一次的任务分发 。
结合图 1 , 如果要做到任务去重 , 系统至少需要提供两个维度的保障:
1、系统侧保障:任务调度系统自身的 failover 不影响消息的传递正确性及唯一性;
2、提供给用户一种机制 , 可以做到整个业务逻辑的触发去重语义 。
下面 , 我们将结合简化的 Serverless Task 系统架构 , 谈一谈函数计算是如何做到上面的能力的 。
函数计算异步任务触发去重的实现 函数计算的任务系统架构如下图所示
图 2
首先 , 用户调用函数计算 API 下发一个任务(步骤 1)进入系统的 API-Server 中 , API-Server 进行校验后将消息传入内部队列(步骤 2.1) 。 后台有一个异步模块实时监听内部队列(步骤 2.2) , 之后调用资源管理模块获取运行时资源(步骤 2.2-2.3) 。 获取运行时资源后 , 调度模块将任务数据下发到 VM 级别的客户端中(步骤 3.1) , 并由客户端将任务转发至实际的用户运行资源(步骤 3.2) 。 为了做到上文中所提到的两个维度的保障 , 我们需要在以下层面进行支持:
1、系统侧保障:在步骤 2.1 - 3.1 中 , 任何一个中间过程的 Failover 只能触发一次步骤 3.2 的执行 , 即只会调度一次用户实例的运行;
2、用户侧应用级别去重能力:能够支持用户多次反复执行步骤 1 , 但实际只会触发一次 步骤 3.2 的执行 。
系统侧优雅升级Failover 时的任务分发去重保证 当用户的消息进入函数计算系统中(即完成步骤 2.1)后 , 用户的请求将收到 HTTP 状态码 202 的 Response , 用户可以认为已经成功提交一次任务 。 从该任务消息进入 MQ 起 , 其生命周期便由 Scheduler 维护 , 所以 Scheduler 的稳定性及 MQ 的稳定性将直接影响系统 Exactly Once 的实现方案 。