亚马逊AWS官方博客

Amazon Lambda 函数配置动态更新方案分析

背景

在现代化应用或微服务分布式系统中,配置中心(Configuration Center)扮演着一个非常重要的角色。它是一个集中式的配置管理系统,用于管理和分发应用程序的配置数据,通常支持“推送”和“拉取”两种获取配置的方式。

当您进行应用现代化转型,尝试使用云原生函数计算服务 Amazon Lambda 承载核心业务逻辑时,可能在配置的动态更新问题上遇到一些挑战。由于 Amazon Lambda 函数的计算模型是短时、按需的函数计算,您无法在 Amazon Lambda 函数中运行 long run 的后台进程或线程,所以您无法和配置中心之间维护一个长连接,无法接受来自配置中心的配置更新推送,只能从 Amazon Lambda 函数主动向配置中心查询配置。

本文将在“从 Amazon Lambda 主动向配置中心查询配置”的基础上,分析不同配置更新方案的优缺点,以便您在架构设计时进行选择。

常见配置中心对于推送模式的支持

如今越来越多现代化的配置中心组件支持使用“推送”模式实现几乎实时的配置更新。以 Nacos 为例,应用除了可以在启动时主动拉取配置,还可以注册监听器,在配置发生修改时触发回调函数,从而几乎实时地更新应用行为。

由于 Amazon Lambda 无法直接接受配置中心的长连接配置更新推送,在下面的方案中,您可能需要将配置的变更通过 HTTP 短链接请求的方式通知给部署在 Amazon Lambda 中的微服务。有两种方式可以实现通过 HTTP 发布配置:

  • 在 Amazon EC2 等可以 long run 的计算实例上注册配置客户端,并订阅相关的配置,在接收到配置之后使用 HTTP 请求将配置发布到 Amazon Lambda 中的微服务。
  • 有些配置中心可以通过插件或者 WebHook 的方式直接使用 HTTP 发布变更,不需要额外的客户端。

仍然以 Nacos 为例,在 2.3.0 版本之后,支持自定义配置变更插件,使开发者可以使用面向切面编程的方式,在配置变更之后拿到更新的配置,以便发出 WebHook 请求。Nacos 官方也开源了 WebHook 插件的参考实现

基于拉取和缓存的配置更新方式

思路

如上文所说,您可以在 Amazon Lambda 函数中主动请求配置中心,从而拉取配置,这样当函数冷启动的时候就会拿到初始配置。为了能够在运行环境销毁之前热更新配置,您通常需要为这些配置设置一个超时时间(TTL)。当函数被触发,并且配置已经过期的情况下,函数需要再次主动请求配置中心从而拿到配置。

实施

如果您将配置保存在以下亚马逊云科技的托管服务中,那么亚马逊云科技提供了开箱即用的插件,帮您拉取配置和管理缓存生命周期,您只需要向 localhost 的指定端口发出请求即可拿到这些配置:

如果您使用在 VPC 中自行搭建的配置中心,您也可以为 Amazon Lambda 函数启用 VPC 访问,并配置好安全组,使其可以访问 VPC 中的配置中心。您可以参考此文档进行配置。

分析

基于拉取和缓存的配置更新方案通常具有分钟级的生效时间,因为缓存的过期时间通常被设置为分钟级。

如果您需要更短的配置生效时间,则需要降低缓存的过期时间,但是这可能导致 Amazon Lambda 函数频繁访问配置中心,给配置中心带来不必要的压力,并且 Amazon Lambda 函数在运行时向配置中心发出请求也会拖慢函数的响应时间。

基于推送与 Amazon EFS 的配置更新方式

思路

Amazon EFS 是亚马逊云科技提供的云原生全托管网络文件系统,可以被 Amazon Lambda 函数挂载。当配置更新时,配置中心主动将配置推送到 EFS。Amazon Lambda 函数在每次调用的时候都可以从 Amazon EFS 读取配置,确保配置是最新的。

实施

您可以参考此文档来创建 Amazon EFS 并挂载到 Amazon Lambda 上。

如果您的配置中心支持通过 WebHook 的方式发布配置更新,您可以接入一个 Amazon API Gateway 和一个 Amazon Lambda,负责更新 Amazon EFS 中的配置信息。

您也可以在一台 Amazon EC2 实例上 mount Amazon EFS 文件系统并更新配置数据,这个 Amazon EC2 实例可以通过配置中心的主动推送来接受配置更新。

分析

此方案的额外成本主要来自 Amazon EFS 的存储和 IO。假设配置文件大小为 5KB,Amazon Lambda 函数读取 Amazon EFS 100 万次,使用 Amazon EFS 标准存储层弹性吞吐模式(默认),在 us-east-1 区域,存储与 IO 成本总和约为 $0.15。您可以参考 Amazon EFS 的定价页面来根据您的实际需求计算成本。

在此方案之上,如果您需要减少 Amazon EFS 的 IO,避免 Amazon Lambda 每次都访问 Amazon EFS 读取配置,也可以添加缓存和过期时间机制。

另外,由于 Amazon EFS 在 Amazon VPC 中,您必须将您的 Amazon Lambda 函数连接到 VPC。

基于推送和环境变量的配置更新方式

思路

如果您的配置内容较少,您可以直接将其保存在 Amazon Lambda 函数的环境变量中,从而避免通过网络获取配置。当配置更新时,您可以修改 Amazon Lambda 函数的环境变量并创建一个新的函数版本进行重新部署。

实施

您可以通过编程的方式来修改 Amazon Lambda 函数的环境变量发布新版本等功能。

当然,如果您使用了一些无服务器基础设施即代码(IaC)开发框架,您可以使用这些开发工具提供的更新和部署方案来更新 Amazon Lambda 函数,而不需要手动调用 API 来实现更新的效果。以 Amazon SAM 为例,它可以通过调用 Amazon CodeDeploy 实现 Amazon Lambda 函数的批量更新、滚动更新、金丝雀发布等功能。

通过配置 WebHook 并使用 Amazon API Gateway,您就可以在配置更新时自动化地更新 Amazon Lambda 函数的版本。

分析

由于此方案 Amazon Lambda 函数部署后不会动态修改配置,而是通过发布新版本来更新配置,所以函数的运行时性能完全不会受到影响,也几乎不存在额外的存储与 IO 成本。

但是需要注意的是,部署新版本时,Amazon Lambda 的并发扩展速度和冷启动可能会影响配置的生效时间。以及,如果直接把所有流量切到新版本,新版本可能由于冷启动而增加响应时间,通过预置并发或 SnapStart 功能可以缓解此冷启动的问题,但是会使配置生效更慢。

最后,Amazon Lambda 函数的环境变量大小上限为 4KB,所以此方案对配置的大小也有要求。

基于推送和拉取的配置更新方式

思路

类似于上文“基于推送和环境变量的配置更新方式”,当配置更新时,您可以创建一个新的 Amazon Lambda 函数版本,来强制重新部署一批 Amazon Lambda 函数实例,并在这些新实例冷启动的时候从配置中心获取配置。

实施

类似于上文“基于推送和环境变量的配置更新方式”,您可以直接调用 Amazon Lambda API 来实现部署,也可以使用 IaC 框架实现渐进部署。

在您的 Amazon Lambda 函数中,您仍然需要主动通过网络请求从配置中心拉取配置,但是因为配置不是保存在环境变量中,所以不会受到环境变量大小的限制。

分析

类似于上文“基于推送和环境变量的配置更新方式”,此方案 Amazon Lambda 函数部署后不会动态修改配置,而是通过发布新版本来更新配置,所以函数的热启动运行时性能完全不会受到影响。但是因为在冷启动的时候仍然需要通过网络访问配置中心,所以冷启动时间会受到影响,并且由于冷启动运行时间变长,Amazon Lambda 的成本也会在部署时略有升高。

由于此方案也会重新创建运行环境,所以配置生效时间也会受到并发扩展速度、冷启动时间和拉取配置延迟的影响,冷启动的问题也存在,可以配合预置并发和 SnapStart 缓解,但是会使配置生效更慢。

另外,部署更新时批量启动的 Amazon Lambda 实例可能也会对配置中心施加突增压力,如有必要可以将配置额外保存在 Amazon S3 或 Amazon DynamoDB 等弹性更强的服务中,避免配置中心被击穿。

总结

下表总结了本文中提到的方案及其优缺点信息,以便您在架构设计时进行参考。

方案 配置更新方式 运行时性能影响 额外成本 生效时间 渐进部署 其他信息
拉取和缓存 拉取 拉取配置时的网络请求会影响性能,取决于缓存 TTL 函数拉取配置时额外运行的时间。取决于缓存 TTL 取决于缓存 TTL,通常配置为分钟级 由配置中心实现或手动实现 需要根据业务需求设计缓存 TTL
推送更新到 Amazon EFS 推送 读取 Amazon EFS 的延迟,毫秒级 Amazon EFS 的存储和 IO 几乎立刻 由配置中心实现或手动实现 函数必须启动 VPC 模式。可以自行添加缓存和 TTL 来减少 Amazon EFS IO。
推送更新到函数环境变量 推送 几乎无 取决于并发扩展速度、冷启动时间和渐进部署方案 因为更新了函数版本,可以使用 Amazon CodeDeploy 渐进部署

可以使用预置并发或 SnapStart 缓解冷启动,但是会使配置生效更慢。

Amazon Lambda 环境变量大小上限为 4KB。

推送触发更新函数版本并重新拉取 推送+拉取 函数冷启动拉取配置导致额外的运行时间 取决于并发扩展速度、冷启动时间、拉取配置延迟和渐进部署方案 因为更新了函数版本,可以使用 Amazon CodeDeploy 渐进部署

可以使用预置并发或 SnapStart 缓解冷启动,但是会使配置生效更慢。

部署更新时批量启动的 Amazon Lambda 可能对配置中心施加突增压力,可以考虑使用外置存储如 Amazon S3 或 Amazon DynamoDB 来缓解。

本篇作者

王景辉

亚马逊云科技无服务器解决方案架构师,负责基于亚马逊云科技无服务器计算与应用集成领域的方案咨询与架构设计,同时致力于亚马逊云科技云服务知识体系的传播与普及。