通过云服务 API 创建无服务器(Serverless)数据库


下面我们来演示如何在 AWS 中创建一个无服务器数据库。

无服务器即 Serverless,并不是真的没有服务器,而是开发者不需要关心和维护对应的硬件服务器资源,而是可以通过软件方式创建和编排服务器,是一种云原生开发模式。国内腾讯云、阿里云亦可,基本流程一样,具体的 API 不同而已,你可以下载对应平台的 SDK,并根据官方文档调用相应的 API 实现。

编写任务类

要实现这个功能,需要创建网络、然后分配访问权限、最后创建数据库。我们为每个操作创建一个对应的任务类。

以上每一步可能都要耗费几分钟才能完成,开始处理时,AWS 会返回 provisioning 状态,我们会监控资源直到状态值变成 active,上一步操作的状态没有变成 active 就不能进行下一步操作。

负责创建网络的 EnsureANetworkExists 任务类的 handle 方法如下所示:

如果网络不存在,则创建一个新的并等待其状态变成 active(通过重新执行任务模拟多进程阻塞)。

负责分配访问权限的 EnsureNetworkHasInternetAccess 任务类 handle 方法与之类似:

最后是负责创建数据库的 CreateDatabase 任务类,其 handle 方法如下所示:

分发任务链

上面三个步骤需要一个接一个运行,如果其中某个步骤执行失败,还需要清理对应资源。

可以将其类比为数据库事务,所有语句执行成功才会提交,否则进行回滚操作。

这是一个典型的责任链模式,在消息队列中,我们可以将其称之为任务链,Laravel 的 Bus 服务提供了分发任务链的方法:

使用 Bus::chain 传入队列任务,然后调用 dispatch 进行分发即可。

和批处理不同,任务链是串行处理的,如果某个任务没有执行成功,则一直重试到成功才会继续执行下一个任务,如果某个任务执行失败,则整个任务链会被删除。

处理任务链执行失败

如果任务链执行失败,则需要回滚所有已执行任务,在某些场景下,这非常简单,只需要删除所有创建的资源即可,在我们这个场景下,稍微复杂一些。

从网络中移除访问权限之前,还需要确保它们没有被其他资源使用。和完全移除网络一样,这个智能移除任务链影响的过程称为「补偿事务」:

首先,我们需要检查网络是否被其他资源使用,如果没有就可以删除了,不过,如果网络被其他资源使用,但是不涉及到访问权限,则只能删除访问权限,不能删除网络。

要运行这个补偿事务,可以在 catch 代码块中处理:

如果任务链中的某个任务运行失败,则会执行 catch 中的闭包函数进行回滚处理。

注:一个任务运行失败意味着已经尝试了该任务类配置的 retries 次数。catch() 方法的闭包函数调用时,队列任务类的 failed 方法也会被调用。

保持补偿事务的精简

catch 中的闭包会在任务用完所有尝试次数后执行,该操作在任务从队列中移除、获取下一个任务之前完成。

如果任务运行时间+闭包执行时间超过了任务的超时时间,队列处理器会立即退出,导致系统出现状态不一致的情况。

所以,要确保 catch 闭包的代码或者任务类的 failed 方法尽可能精简,如果你想要执行更多工作,可以将其分发到另一个队列任务中执行:


Vote Vote Cancel Collect Collect Cancel

<< 上一篇: 异步高效处理视频上传

>> 下一篇: 基于任务链和批处理生成复杂报告