Serverless

Serverless 概念与实践 本文介绍 Serverless 的模型、权衡和开源实现。事件格式和消息语义见事件驱动架构,Kubernetes 上的 Serving/Eventing 平台见 Knative。 开发分布式应用程序的通用需求 生命周期管理(lifecycle) 管理应用程序除开发过程

Serverless

概念与实践

本文介绍 Serverless 的模型、权衡和开源实现。事件格式和消息语义见事件驱动架构,Kubernetes 上的 Serving/Eventing 平台见 Knative。

开发分布式应用程序的通用需求

生命周期管理(lifecycle)

示意图

  • 管理应用程序除开发过程之外的整个生命周期

  • 打包、部署、配置、卸载

  • 扩容、缩容、健康状态

网络管理(networking)

  • 在不可靠的网络中建立起可靠的通信

  • 实施高级流量治理策略

资源绑定(binding)

  • 负责在需要通信的对象之间建立通信路径

  • 连接器、协议、消息路由、事务等

状态管理(state)

  • 应用程序根据各类输入的信息生成存储结果后所处Condition即为状态,而状态管理负责将应用程序的状态以特定数据结构向外暴露,以便于程序员使用

  • 工作流管理、幂等、缓存……

分布式通信中的网络通信管理

分布式计算中的8大悖论(Fallacies)

①The network is reliable. →网络可靠②Latency is zero. →零延迟③Bandwidth is infinite. →带宽无限④The network is secure. →网络很安全⑤Topology doesn't change. →网络拓扑稳定⑥There is one administrator. →只有一个管理员⑦Transport cost is zero. →传输成本为零⑧The network is homogeneous. →网络同质

在分布式应用组件间建立起可靠、稳定的通信,需要解决的关键问题

  • 服务容错:超时、重试、熔断

  • 服务调用:RESTful、RPC

  • 可靠地变更和发布:A/B Testing、Canary Rollouts、Blue-Green

  • 服务发现:服务注册和服务发现

  • API管理和服务网关

  • 可观测性

分布式通信中的资源绑定

命名(Naming)和绑定(Binding)是计算机系统中的基础概念,前者负责处理如何符号化引用系统中的各种资源,后者负责解决如何通过名称对资源进行访问

  • 名称是与对象相关联的信息(元数据),负责实现两个功能

  • 标识对象:用户标识的名称应该同它所标识的对象持久、明确地关联

  • 为对象提供一个访问路径:该名称所代表的对象支持在物理意义上(即具体的存储位置)进行定位

  • 绑定是指在计算机系统中互连一组对象的过程,该过程的结果,即在对象之间创建的关联或者链接,称之为绑定

  • 绑定的目的是创建一个访问路径,一个对象可通过该路径访问到另一个对象

  • 例如,将变量的标识符同包含其值的存储位置相关联,以及RPC中创建的远程连接等

  • 绑定可以在编程语言、操作系统或者网络级别完成,但混合多种级别的解决方案更常见

绑定发生的时间

  • 静态绑定,例如绑定到常量值

  • 编译时绑定,例如编译器将变量标识符绑定到内存段中的偏移量

  • 链接时绑定,例如链接器查找各搜索路径以找到那些编译后仍未解析的名称对应到的对象

  • 动态绑定,即运行时绑定

分布式绑定模型

集中式绑定与分布式绑定

  • 单体系统中,可以直接使用内存地址来访问该地址中的对象

  • 分布式系统中,远程对象不能直接引用,而是要先构建涉及网络协议的访问链,然后才能完成对象绑定;基于Socket进行的C/S连接更为常见

示意图

服务提供模型,由service provider、service requester和service directory按如下步骤进行

  • Service creation

示意图

  • Service registration

  • Service lookup

  • Service binding

  • Service access

分布式通信中的状态管理

Application State

  • 应用程序的状态,是指程序在给定时刻的具体状况(Condition)或特征

  • 应用程序是Stateful还是Stateless,取决于与其交互的状态被记录的时长,以及状态的存储方式

  • Stateless:每个请求事务都完全从0开始,没有存储的信息,也无须参考过去的事务,例如搜索事务等

  • Stateful:每个请求事务都是在先前事务的Context中执行,并受到这些Context的影响

State Manager

  • 状态管理负责在应用程序的各组件之间同步状态信息

  • 可有效提升应用程序处理数据的效率,尤其是应用程序包含大量的组件,并且有很多请求都需要发送到后端进行数据检索时更是如此

示意图

ASP.NET中的状态管理机制

多运行时微服务

生命周期管理:Kubernetes网络通信:Service Mesh

示意图

  • 专注于分布式应用的高级网络通信需求,即“网络”服务网格

资源绑定:Knative

  • Serverless Platform

  • 专注于Serverless,同时兼顾了服务编排和事件驱动的绑定需求

状态管理:Dapr

  • 分布式应用运行环境 (distributed application runtime)

示意图

  • 与专注于网络问题的ServiceMesh不同,Dapr专注于提供构建基块,使开发人员更容易将应用程序构建为微服务

众所周知的云计算模型

示意图

传统模型下的应用部署上线过程

如今,大多数公司在开发应用程序并将其部署、运行在服务器上的时候(无论是选择公有云还是私有的数据中心),都需要提前完成如下步骤

  • 容量规划:提前了解究竟需要多少台服务器、多大容量的存储和数据库的功能等

  • 部署运行应用程序和依赖的软件

概括来说,需要上线运行一个新的软件项目时,在编写代码之前,在IaaS或CaaS云环境下,需要完成

  • 准备Server

①登录云控制台②创建实例、启用实例③选择操作系统、并确定实例规格和类型④配置实例详细信息:数量、网络、IP地址、监控和其它扩展⑤添加持久存储⑥安全设置⑦部署、初始化应用运行环境,并尽量和本地开发环境保持一致⑧设置接入层的反向代理实例,配置反向代理⑨购买域名,配置域名解析记录指向反向代理

  • 设定中间件和数据库等支撑系统

①选择云供应商提供的服务或自行部署及管理

Serverful 环境下的应用上线过程

示意图

图源:https://time.geekbang.org/

Serverless 环境下的应用上线过程

示意图

Serverless 将服务器置备、容量管理和扩缩容等基础设施工作交由平台处理。HTTP 请求到达时,平台按并发和容量策略将其路由到可用实例,必要时创建实例;函数或服务返回的结果再由平台回传。具体是否排队、等待或返回超时取决于平台配置。

图源:https://time.geekbang.org/

函数的冷启动

冷启动是平台为处理请求而准备新实例所增加的启动过程,可能包括调度、拉取镜像、启动运行时和初始化代码。实际耗时受平台、镜像大小、运行时和初始化逻辑影响;冷启动快慢并不直接决定资源利用率。

  • 镜像预构建或缓存可减少启动时的构建和下载开销,但不能保证实例已运行;首个请求仍可能等待实例启动。

  • 预置或保留实例可以降低部分请求的冷启动概率,但会增加资源成本,且具体行为由平台配置决定。

示意图

函数实例的层级结构

函数实例通常可分为三个层级:容器、Runtime和函数代码

示意图

  • 容器:抽象的计算资源和操作系统环境,负责为Runtime和函数代码的运行提供基础设施

  • 函数的Runtime

Runtime(运行时)提供函数代码执行所需的语言环境、调用约定和系统接口。平台可能提供内置运行时,也可能允许自定义镜像;运行时是否可自定义取决于产品。

  • 函数代码

函数代码由用户编写。实例可能在空闲后被回收,也可能按平台配置保留或预置;代码不应依赖本地临时文件或进程内状态来实现跨实例持久化。需要持久化的数据应存入外部存储或托管服务。

这种按需创建运行函数的服务平台即为FaaS

将数据持久化交由BaaS

什么是BaaS?

示意图

  • 为FaaS等提供依赖到的各类基础设施型服务

  • 由多种基础设施类的服务所组成的集合

  • Database Management

  • Cloud Storage and automated data backups

  • Identity and access management (IAM)

  • Email and SMS push notifications

  • Social media Integration

  • Location-based services

  • Infrastructure management

  • API management

  • ……

BaaS化的核心思想

  • 将各类后端应用转换成无需用户运维的数据接口

  • 后端服务最好能将函数操作数据的调用,封装成基于HTTP的OpenAPI,从而能够方便地控制API的请求频率并在必要时实施限流降级

  • 将后端服务Serverless化,并提供给前端使用(SFF:Serverless For Frontend)

Serverless的概念梳理

Serverless的含义

  • 通常被直译为“无服务器计算”,它的真实意思是“服务器无感知”,或者用户“较少关心服务器”

  • 也是一种架构设计理念,即Serverless Computing 架构或FaaS架构,而非一个具体的编程框架、类库或者工具

  • 常见的 Serverless 应用会组合事件触发、FaaS 和托管后端服务(BaaS),但这是一种概括模型,不是严格等式或统一产品定义。

在Martin Fowler看来,“Serverless就是FaaS和BaaS的组合”

  • FaaS

  • FaaS 让事件或 HTTP 请求触发函数代码,平台负责函数实例的调度和扩缩容;执行时限、并发、运行时和调用方式由产品定义

  • BaaS

  • BaaS 将数据库、对象存储、身份认证、消息和通知等托管能力通过 API 提供给应用

BaaS和FaaS特性总结

BaaS

  • 云服务端将后端需要的各种服务,例如认证服务、数据库、消息队列、文件存储、代码构建等各种后端功能封装为API提供给用户

  • 用户只需要根据BaaS的API编写并提交代码即可自动完成应用构建、部署、运行、扩缩容等功能

FaaS

  • 通过事件或请求触发函数代码的计算模型;底层基础设施由平台管理

  • 开发人员编写逻辑代码,并将其部署到完全由平台(云服务商)管理的容器中,然后按需执行

  • 函数可以经 API Gateway、消息系统、定时器或其他事件源触发;API Gateway 并非所有调用的必经组件

  • 运行Serverless代码的容器的特点

  • 实例可以复用、预留或在空闲后回收;生命周期由平台决定。

  • 横向扩缩容时,不应依赖单实例内存或临时文件保存跨请求状态。

  • 触发器可以是 HTTP 请求、消息、定时器或平台集成事件。

  • 平台管理底层基础设施,但应用权限、依赖、数据和业务可靠性仍由团队负责。

BaaS与FaaS的区别

BaaS处理整个后端功能,而FaaS仅处理应用程序中支持响应的事件

示意图

Serverless的发展历程

Serverless 一词在 2010 年代中期随云函数服务普及。早期托管执行服务已有按需运行和按量计费的相似理念;具体产品和术语起源不宜简化为单一“首创者”。

示意图

图源:https://time.geekbang.org/

Serverless产品分类

Serverless技术和产品的分类

  • 函数计算(FaaS)

  • 面向函数代码,适合边界明确、可由事件触发的任务;需评估启动延迟、状态外置、执行时限和调用成本

  • Serverless应用托管

  • 面向应用或服务,平台接管部分部署、治理和扩缩容工作;迁移既有应用仍需评估运行时、网络、状态及可观测性差异

  • Serverless容器服务

  • 面向容器,平台根据请求或事件管理容器化工作负载;底层仍需集群容量、网络和存储规划

Serverless内涵及适用场景的进一步发展

  • 随着发展,如今的Serverless概念内涵已经不再局限于原来狭义上的FaaS和BaaS,而是开始扩展到了Serverless DB、Serverless MQ、工作流、工具链等方面

  • 另外,Serverless的应用场景也不再局限于小程序、定时任务、简单事件的触发和批量场景的处理,而是业已渗透进了IoT数据处理、大规模数据的处理、微服务托管上云和基于AI的集成等领域

Serverless的优缺点

优点

  • 较低的运维成本

  • 较低的开发成本

示意图

  • 自动化弹性扩展

  • 较高的计算资源利用率

缺点

  • 仅支持无状态服务

  • 延迟问题

  • 冷启动、网络调用和托管依赖可能增加延迟,实际影响取决于平台、运行时和负载。

  • 尚未形成统一标准

  • 存在厂商锁定的可能性

Serverless的主流产品

云厂商托管式的FaaS产品

  • AWS Lambda

示意图

  • Google Cloud Functions

  • Microsoft Azure Functions

  • Aliyun Function Compute

  • Huawei Cloud FunctionGraph

  • ……

开源解决方案

  • Apache OpenWhisk

  • OpenFaaS

  • Fission

  • Kubeless

  • Knative

Serverless概念总结

Serverless的基础概念

  • 云原生开发模型的一种,可使开发人员专注于构建和运行应用,而无需管理服务器

  • Serverless方案中仍然需要服务器,但它们已从应用开发人员的关注中抽离了出来

  • 云提供商负责置备、维护和扩展服务器基础架构等例行工作

  • 开发人员可以简单地将代码打包到容器中进行部署

  • 部署之后,无服务器应用即可响应需求,并根据需要自动扩容

  • 用户为实际占用的资源付费,而不再是固定的带宽或者服务器数量

Serverless与其它云计算模型的核心区别

  • 由云服务商负责管理基础架构和应用扩展

  • 应用部署于容器中,这些容器在被调用时将会自动按需启动

  • 出现能够触发应用代码运行的事件时,云架构才会为这一代码分配资源

  • 代码执行结束后,占用的大部分资源便即释放

  • 帮助公司避免服务器等资源的过渡采购,提高资源效益

  • 操作系统、文件系统、安全补丁、负载均衡、容量管理、扩展、日志和监控等例行任务都由底层的云服务完成,从而将开发人员从应用扩展和服务器置备相关的琐碎日常任务中解放出来

现代系统常组合使用 Serverless、微服务和长期运行的服务。

Serverless核心理念

示意图

图源:https://time.geekbang.org/

用户视角下的函数计算过程

函数的整个生命周期会经过“开发设置”、“打包上传”、“事件绑定与触发”、“弹性执行”和“实例销毁”五个过程

示意图

在前端界面手动点击等方式来执行函数,也可以通过各过触发器来触发函数的执行

图源:https://time.geekbang.org/

平台视角下的函数计算过程

用户上传代码到FaaS平台后,后端服务会将代码包上传到对象存储中,并将函数相关信息,包括函数代码链接、Runtime信息、运行内存、超时时长等信息予以存储,接下来即可由相关事件触发执行

示意图

实例回收、请求排队、激活器和空闲保留时间均由具体平台实现,不能假设所有平台都会采用固定的 1–2 分钟保留时间。

实例数量要根据请求的规模自动进行缩放,缩放算法需要包含Node级别和Pod级别; Kubernetes的HPA和CA(Cluster AutoScaler)就具有类似的功用

Image后以容器形式运行;

图源:https://time.geekbang.org/

CNCF定义的4种调用函数服务的方式

CNCF Serverless 白皮书归纳了常见函数调用模式。具体支持项取决于平台;此图用于概念分类,不代表所有平台实现相同接口。

示意图

事件源与函数计算

事件驱动计算:事件源负责生产事件,目标函数根据从事件源接收到的事件执行相应的处理动作

  • 上传至Serverless平台的云函数,一般需要由某个事件触发才能执行

  • 事件自身不包含路由信息,它需要某于某个消息机制传递给消费者,例如通过发布/订阅模式的Kafka等系统完成消息封闭和发送

  • 对函数计算来说,触发器描述了一组关系和规则,包括事件源、目标函数和触发条件

事件源

事件就是系统运行期间发生的动作或者发生的事情,是过去某

生成事件

一时间点的记录

触发函数计算

由事件驱动连接上下游服务的关系组合称为触发器,它是触发函数执行的主要方式

目标函数

接收触发请求

合法性验证

解析对应函数

执行函数

函数间的调用

出于复用、部署和扩缩容等考虑,应用可能拆分为多个函数或服务。函数间调用可采用同步请求、异步消息或工作流编排;拆分会增加网络故障、重试和可观测性方面的治理成本。

示意图

  • 同步调用:常用于调用时间少、需要及时返回处理结果、业务处理较为简单的场景

  • 异步调用:能增大并发,以及尽可能地节省调用成本,但客户端无法第一时间获利调用结果,因而适用于对延时不敏感、无需等待返回给客户端结果的场景下使用

  • 编排:函数之间不再以主动或被动的触发方式来交互,而是依照预制好的步骤进行

这种编排执行的方式,也可称为Serverless Workflow,它允许用户通过顺序、分支、并行的方式来协调一个或多个分布式任务

Cloud-Native FaaS Function 项目示例

OpenFunction

  • 云原生、开源的 FaaS(函数即服务)框架,旨在让开发人员专注于业务逻辑,而不必关心底层运行环境和基础设施

示意图

OpenFunction上函数的生命周期

示意图

Function CRD是用户调用OpenFunction的入口

Function是Build和Serving的控制平面,可按需自动创建Build和Serving

基于Serving CRD创建,为Function提供Runtime

OpenFunction支持的Runtime

OpenFunction支持的Runtime主要有Sync和Async两类

示意图

函数Runtime概述

运行时(Runtime)

  • 全称为运行环境(Runtime environment),又称为运行时系统(run-time system),是一种半编译的执行码在目标机器上运行时的环境,也是一种介乎编译器与解释器之间的代码执行方式

  • 大多数编程语言都有某种形式的运行时系统,用于为程序提供运行的环境

  • 这个环境可以解决很多问题,包括应用程序内存管理、程序如何访问变量、程序之间的参数传递机制、与操作系统的接口等问题

  • 通常情况下,运行时系统承担一些设置,以及管理堆和栈的责任,并可能包括诸如垃圾回收、线程或其他内置于语言中的动态功能

函数计算运行时(Runtime)本质上就是一个让函数在容器中执行起来的框架

  • 函数Runtime负责支撑函数在机器或容器中运行起来,实现业务逻辑的执行环境,通常由特定语言的构建框架所构成

  • 函数计算的Runtime依赖于函数代码相关编程语言的Runtime,但更贴近应用

初始化

Runtime Function

进程

工作流编排

编排Serverless Function

  • 对由十几个甚至几十个function组成的业务来说,协调这些function执行的复杂度将成为一个艰巨的任务

  • 函数拆分越细,部署、重试、幂等和可观测性治理越复杂

  • 工作流可按事件或状态进行顺序、并行和分支执行

  • Serverless Workflow(工作流)就专用于解决这种function编排相关的复杂性

工作流的定义

  • 维基百科给出的定义是:“对工作流程及其各操作步骤之间业务规则的抽象、概括描述。”

范,以促进Serverless应用程序在不同厂商平台之间的可移植性

  • CNCF Serverless Workflow规范是一种用于微服务、事件和函数编排的工作流语言规范,可以通过YAML或JSON的格式

描述和定义工作流

  • CNCF Serverless Workflow规范专门针对Serverless技术领域,所以关注点会在事件驱动应用、函数或微服务

CNCF Serverless Workflow 规范是一种基于通用的、声明性的思路提炼出的工作流规范,且支持通过YAML或JSON的格式描述和定义工作流,更容易表达像functions, events, retries这些无服务器技术领域的元素

评论