1.2.2 Serverless关键技术
图1-8是典型的Serverless系统架构,从中可以看到一些Serverless的常用概念。
图1-8 典型的Serverless架构
• 事件源(Event Sources):事件的生产者,可能是HTTP请求、消息队列的事件等,通过同步或异步的方式去触发函数。
• 触发器(Trigger):函数的REST呈现,通常是RESTful URL。当事件源将事件推/拉到触发器时,FaaS平台会查找触发器和函数的映射关系,从而启动该函数实例,以响应被推/拉到触发器的事件。
• FaaS控制器(FaaS Controller):FaaS平台的核心组件,管理函数的生命周期、扩容和缩容等。可以将函数实例缩容为0,同时在收到对函数的请求时迅速启动新的函数实例。
• 函数实例(Function Instance):执行函数的环境,包含函数代码、函数运行环境(如JRE、Node.js)、上下文信息(如函数运行的配置,通常以环境变量注入)。一个函数实例可以同时处理1个或N个事件(取决于平台的具体实现)。函数实例通常内置可观测性,将日志和监控信息上报到对应的日志和监控服务中。
• 函数编程模型(Programming Model):通常表现为函数的编码规范,如签名、入口的方法名等。函数的编程模型一般会提供同步/异步/异常处理机制,开发者只需要处理输入(事件、上下文),并返回结果即可。
• BaaS平台:函数通常是无状态的,其状态一般存储在BaaS服务中,如NoSQL数据库等。函数可以基于REST API或BaaS服务提供的SDK来访问BaaS服务,而不用关心这些服务的扩容和缩容问题。
结合图1-8中典型Serverless架构的架构元素,从Serverless系统的实现来看,其关键技术需求包括以下几点。
• 函数编程模型:提供友好的编程模型,使开发者可以聚焦于业务逻辑,为开发者屏蔽编码中最困难的部分,如并发编程等。同时,需要原生支持函数的编排,尽量减少开发者的学习成本。
• 快速扩容:传统的基础设施通常都是从1到n扩容的,而Serverless平台需要支持从0到n扩容,以更快的扩容速度应对流量的变化。同时,传统基础设施基于资源的扩容决策周期(监控周期)过长,而Serverless平台可达到秒级甚至毫秒级的扩容速度。
• 快速启动:函数被请求时才会创建实例,该准备过程会消耗较长的时间,影响函数的启动性能。同理,对于新到达的并发请求,会产生并发的冷启动问题。Serverless平台需要降低冷启动时延,以满足应用对性能的诉求。
• 高效连接:函数需要将状态或数据存放在后端BaaS服务中,而对接这些服务往往需要繁杂的API,造成开发人员的学习负担。如果能提供统一的后端访问接口,则可以降低开发和迁移成本。另外,Serverless平台的函数实例生命周期通常较短,对于如RDS数据库等后端服务无法保持长连接。然而,在并发冷启动场景下,大量函数实例会同时创建与数据库的连接,可能会导致数据库负载增加而访问失败。为此,Serverless平台需要为函数提供完备、高效、可靠的BaaS服务连接/访问接口。
• 安全隔离:Serverless是逻辑多租的服务,租户的函数代码可能运行在同一台服务器上。基于容器的方式,一旦单个租户的函数遭受攻击,造成容器逃逸,会影响服务器上所有租户的函数安全。所以,通常Serverless平台会采用安全容器的方式,引入轻量级虚拟化技术来保证隔离性,但这同时会引入额外的性能(启动)和资源开销等问题。因此,Serverless平台需要兼顾极致性能和安全隔离。
虽然业界涌现的各种Serverless系统在实现上可能有所不同(如本节介绍的多个函数计算平台),但基本的概念、原理和关键技术是相通的,各个系统在实现时都需要应对以上所述的技术挑战。