定义Serverless场景下BaaS访问的统一范式
在 Serverless 场景下,业务函数需要访问后端服务,如对象存储、消息队列、云数据库等。这些后端服务的接入,涉及到接口标准、海量连接、弹性伸缩、事务语义等问题,给开发者带来了诸多挑战。为了解决这些问题,华为云 FunctionGraph 提出了一种基于代理函数的后端服务接入框架,它可以帮助应用服务实现高效解耦,让开发者专注于业务逻辑,提高函数访问后端服务的效率和体验。
作为一种新兴云计算范式,Serverless 让开发者可以在不管理服务器或后端基础设施的情况下,构建和运行应用代码。Serverless 具有以下特点:编程简单、弹性伸缩、按用付费、无需运维。目前,许多云服务提供商都推出了自己的 Function-as-a-Service (FaaS) 产品。FaaS 可以让开发者在响应特定的事件或请求时,运行应用代码,而无需指定或管理运行代码所需的基础设施。FaaS 的早期形态以无状态为主,每个函数可以看做一个独立的功能模块,不依赖于之前的事件或用户交互。这种无状态的函数非常适合函数按需使用、用完销毁的模式。然而,无状态函数并不能满足一些复杂业务的需求,例如需要在函数之间传递和保存数据的业务场景。为解决这类问题,云服务商们相应推出了如对象存储、消息队列、云数据库、分布式缓存等 Backend-as-a-Service (BaaS) 作为 Serverless 生态的重要部分。简单来说,当下的 Serverless 计算,可以认为是 FaaS + BaaS 的组合。然而,FaaS + BaaS 的架构和 Serverless 所期望的简易编程、高效开发等理念之间,依然存在一定的差距。
一方面,应用在使用后端服务时,通常需要开发者集成对应后端服务的 SDK。即使是相同功能的服务,不同云厂商会涉及不同的操作接口,比如 AWS 的 S3 和 Azure storage。开发者需要学习大量后端服务的使用方式,才能完成业务功能的开发。同时,对于应用本身而言,集成大量相似的 SDK,是一件代价极高的事情,除了增加应用本身的资源消耗(如软件包大小、冷启动时长),还会带来大量的源码维护成本。当应用期望切换部署平台时,往往需要集成对应平台 BaaS 的 SDK,并且重新开发适配这套 SDK 的代码。
另一方面,使用函数实现的应用程序和后端服务的交互往往比较复杂。由于上下文信息被卸载到了后端的 BaaS,因此 BaaS 通常需要维护一个有状态的客户端,包括认证信息、活动的连接等等。比如数据库的事务操作,就需要在同一个数据库连接上执行。在无状态的函数之间传递这些“状态”,无疑是十分复杂的。以多函数共同执行数据库事务为例,这些函数实例无法使用同一个数据库连接,为了在任务失败的情况下进行数据库补偿,业务代码里不可避免地需要编写各种异常处理的逻辑,还需要在任务失败的时候进行失败信息的传递。这无疑也增加了开发者的负担,更重要的是,复杂的逻辑往往会带来意想不到的问题,最终可能使得业务受损。
图 1 使用 Proxy 方式访问后端服务
在应用程序与后端服务之间,增加一层代理,是访问复杂的后端服务的一种常见的方式。在 Serverless 场景,函数的弹性伸缩特性使得应用程序会与后端服务频繁建立和释放连接,从而影响后端服务的正常使用。通过 Proxy 代理访问后端服务,利用池化和共享连接,可以将多个应用程序之间的请求汇聚,从而提高后端服务的效率和业务应用的可扩展性。此外,由于与后端服务的连接是由 Proxy 代理控制的,通过控制请求建立连接对应的后端节点,业务可以通过 Proxy 使用负载均衡、读写分离、故障转移等高级特性。当前比较常用的后端 Proxy 服务有 RDS Proxy[1] 和 Redis Proxy[2],对于大部分后端服务来说,还缺少通用的 Proxy 接入方式。
图 2 通过 Dapr 访问后端服务 [3]
Dapr 是一个实践 Multiple Runtime 理念的开源项目,它将这些许多不同分布式能力以及中间件能力的“运行时”模块进行了整合。Dapr 将分布式应用常用的后端中间件、存储等服务进行抽象,设计出一套标准的接口,然后通过具体的 Sidecar 适配不同的组件实现,应用代码通过 Sidecar 访问后端组件。通过模型抽象预定义 API,替代用依赖库调用中间件,有助于松耦合,开发者可以自由地切换后端中间件,而无需改造代码。在 Serverless 场景,为了减少资源开销,Dapr 一般会与业务函数实例部署在同一容器下,以 Sidecar 进程的方式存在。当函数实例接收到请求之后,可以通过 Dapr 的 SDK 发起对后端服务的调用,Dapr 的 Sidecar 进程会根据接收到的请求选择对应的组件,从而请求后端服务。
图 3 通过 Service Bridge 访问后端服务
Service Bridge 致力于构建一个丰富高效的 Serverless 后端服务环境,由华为云 FunctionGraph 提出。它提供了一系列统一的接口来解耦常用的后端服务的接口和功能实现,比如 OBS、SQL 数据库等等。这样一来,开发者在访问不同云供应商的后端服务时,不需要集成多个类似但不同的 SDK。同时,Service Bridge 为应用开发者们提供了一个可扩展的方式,来实现他们自己的 bridge 函数与特定的 BaaS 服务交互。通过这样的方式,用户各类请求通过统一的接口可以通过特定的 bridge 函数转换成对应的后端服务需要的请求。Service Bridge 以函数方式实现,天然支持自动弹性扩缩容和动态插拔,提升了资源利用率。为了减轻开发者使用负担,Service Bridge 对于业界流行的接口、框架(如 JDBC、Mybatis)也进行了适配支持,开发者无需修改代码,即可直接对接到 Service Bridge。
Service Bridge 通过 Bridge 函数维护和后端服务的连接,通过复用 Bridge 函数,就可以复用后端服务的连接。通过后端连接复用,可以实现(1)高并发请求支持(2)共享已建立好的连接,加速业务启动(3)保证多个业务函数之间共享事务一致性
图 4 多语言场景使用 Dapr 访问后端服务 [5]
首先,Serverless 场景,FaaS 对于多语言的诉求十分强烈,开发者使用各种语言来开发他们的 FaaS 业务。然而,在多语言的支持方面,不是所有的后端服务都有着完备的 SDK。对于开发者来说,自行实现对接后端的 SDK 是不现实的。通过 Dapr,开发者可以很方便地使用不同的语言进行业务开发,同时,也能够使用需要的后端服务。其次,不管是新开发一个应用,还是对于现有应用程序进行迭代演进,Dapr 的多语言支持都十分有效。
除此之外,Dapr 对于后端服务的抽象,使得开发者可以不必关注具体的产品,从而能专注业务开发,提升开发效率。举个例子,一个微服务应用需要使用云上的某个云产品,使用 Java 语言,要引入 maven 依赖,同时需要写一些与后端交互的代码。但是,通过调用 Dapr SDK 提供的 Binding 方法,就可以省去这些步骤,减少维护的开销。
图 5 业务改造前后访问中间件示意图
某 2C 业务基于 Service Bridge 进行改造,完成业务逻辑与后端服务对接分离。原中间件 SDK 从函数里剥离,相关功能下沉到 Service Bridge,减少不必要的依赖,实现函数轻量化。通过复用 Bridge 函数实现连接复用,支持对海量连接和请求进行聚合,减少后端服务压力,提高服务访问性能,用户函数可以做到真正的按需弹性
图 6 Service Bridge 支持分布式函数共享事务
通过 Service Bridge 代理后端服务访问,利用路由计算,将同一事务的请求汇聚到同一个 Bridge 函数实例上,将原来拆分出来的事务逻辑重新聚合成本地事务,解决一致性问题。
图 7 Service Bridge 应用于冷启动快照恢复场景
快照冷启动方案能够加速函数的启动时间,但是也面临着一些挑战:通过快照恢复后,应用的网络连接状态会受到影响,跟外部服务之前已建立的连接都会丢失,需要重新建立 [6]。利用 Service Bridge 充当用户应用与 BaaS 之间的纽带,通过 Bridge 函数保持后端连接,避免应用恢复后等待连接重建,或者侵入业务代码进行 Restore Hook 刷新。
表 1 分别从适用场景、学习成本、是否常驻、业务函数可扩展性、多语言支持方面比较三种对接方式
本文主要讨论了 Serverless 场景下函数访问后端服务的三种接入方式,除了业界熟知的 Proxy 和 Dapr,还介绍了 Service Bridge,一种使用函数代理的 BaaS 访问模式。当然,这三种方式都是通过代理层访问后端,比起直连不可避免地存在性能损耗;同时,统一接口的对接方式面临着后端服务高级特性接口难以统一的挑战,我们也在持续探索和尝试更多的可能。
FunctionGraph[7] 作为华为元戎加持的下一代 Serverless 函数计算与编排服务,集成 Service Bridge,持续为用户带来更好的函数开发、使用体验。后续我们将分享更多围绕通用全场景 Serverless 的前沿理论及其案例实践,回馈社区,包括 FunctionGraph 在微服务 Serverless 化上的实践经验等。
参考资料
[1]https://aws.amazon.com/cn/rds/proxy/
[2]https://support.huaweicloud.com/productdesc-dcs/CacheProxy.html
[3]https://docs.dapr.io/operations/hosting/kubernetes/kubernetes-overview/
[4]https://developer.aliyun.com/article/785943
[5]https://blog.dapr.io/posts/2021/03/19/how-alibaba-is-using-dapr/
[6]https://xie.infoq.cn/article/c10f263d96bb12f02347efc9e
[7]https://support.huaweicloud.com/functiongraph/index.html
[8]https://www.infoq.cn/article/vae6wfvzlferex4navnu
[9]https://skyao.io/post/202103-how-alibaba-is-using-dapr/
微信扫码关注该文公众号作者