4.3 FaaS函数运行时关键技术实现
4.3.1 FaaS-Nomad-Provider的实现
如上述图4.2所示,FaaS-Nomad-Provider通过实现faas-provider将Nomad作为容器编排运行时接入到OpenFaaS生态中,提供了CRUD函数和调用函数等功能。
FaaS-Nomad-Provider接入Nomad编排等功能实现的过程,概括地说在于调用Nomad、Consul、Vault、Statsd等客户端API,在调用过程中,进行认证和缓存优化,如缓存函数名等。如图4.6所示,具体要实现FaaS处理相关的Handler,提供FaaS-Nomad-Provider的FaaSHandlers。
图4.6 FaaS处理相关的Handler
FunctionProxy是一个处理函数的中间件,在下一个HandlerFunc处理前验证了请求参数中函数名是否存在。HandlerFunc实现了Handler接口的ServerHttp方法,所以是Handler的具体类。借助http.HandlerFunc类型可以让常规函数满足作为Handler接口的条件。
以下分为初始化、工作机制两部分详细说明。如图4.7所示,初始化部分创建了Nomad、Consul、Vault、Statsd等依赖组件的API客户端,身份认证,并根据依赖组件创建了接入Nomad具体的FaaSHandlers。FaaS-Nomad-Provider的Serve将路由与处理请求的Handler绑定。
图4.7 FaaS-Nomad-Provider流程图
API网关是OpenFaaS最为重要的一个组件,实际上API网关就是一个REST转发服务,通过一个一个的Handler,每个模块之间的耦合度不是很高,可以很容易的去拆卸,自定义实现相应的模块,本文做了一些的修改。FaaSHandlers中的Handler在API网关处设置相应的路由。
工作机制是由上游网关转发给FaaS-Nomad-Provider处理,FaaS-Nomad-Provider启动了一个服务器默认阻塞在8080端口,接受API网关路由到Provider的调用请求将职责委派给Nomad。具体地,FaaS-Nomad-Provider下游函数是Nomad的作业方式组织运行的,且当前特定的是打包成Docker镜像(其中有watchdog,来启动和监控函数进程),通过Nomad的Job相关API处理CRUD函数、调用函数、设置副本数的请求。
以部署函数实现为例,FaaS-Nomad-Provider参与的工作机制如图4.8所示。
图4.8 部署函数工作机制时序图
1. 用户通过UI/CLI/REST接口向API网关发送部署函数的POST请求,endpoint为/system/functions。这是个同步调用的过程。
2. 所有的请求都要通过API网关,进行认证、缓存优化、监控数据采集等。验证失败则返回,非200状态码都属于验证失败。
3. API网关本身不做任何和部署发布函数的事情,遵循单一职责原则,它只是作为一个代理,把请求转发委派给相应的Provider去处理,向faas-provider发送函数请求部署。
4. faas-provider相当于一层shim,本文中具体是FaaS-Nomad-Provider。FaaS-Nomad-Provider解析部署函数的请求体获得CreateFunctionRequest,调用Nomad等依赖组件的API库实现DeployHandler,封装好Job结构所需的TaskGroup、Task等作为请求体。
5. 到Nomad编排层面就是创建Job的声明式部署请求。
6. Nomad进行评估和分配的调度。
7. 作为Nomad的容器负载,函数在从镜像仓库拉取函数镜像后运行。用户
以上部署函数通过实现DeployHandler,其他Handler也类似,调用依赖的Nomad等组件的API。
4.3.2 缩容到零
缩容到零是指FaaS函数运行时请求驱动的计算,当函数部署没有接收到通信流量时从1/1或N/N副本缩容到0/0副本。流量是通过FaaS API网关收集的Prometheus指标观测的。缩容到零功能作为FaaS-Idler单独实现和部署。自动扩缩容需要Prometheus监控组件,Prometheus服务必须处于可用状态,函数计算服务监控详见6.2。
如表4.1所示,提供以下配置参数进行控制。
表4.1 缩容到零相关配置参数
| 参数 | 说明 | 默认值 |
|---|---|---|
| faas.scale.zero | 函数配置是否缩容到零的标签 | false |
| gateway_url | FaaS-Idler对接的FaaS API网关,不可缺省 | - |
| prometheus_host | FaaS-Idler查询的Prometheus主机地址,不可缺省 | - |
| prometheus_port | FaaS-Idler查询的Prometheus主机端口 | 9090 |
| inactivity_duration | 函数不活跃持续的时间,则执行缩容到零操作 | 5min |
| reconcile_interval | 重新协商的时间间隔 | 30s |
在FaaS API网关中增加Prometheus histogram类型监控指标gateway_function_invocation_total,度量函数调用次数。组件和交互关系如图4.9所示。
图4.9 FaaS-Idler实现缩容到零
1. FaaS-Idler查询FaaS API网关获取所有的函数。
2. 构建MetricsMap,一个以函数名为键,指定间隔内的调用次数为值的键值对,如果值为0,表示该函数不活跃。构建的过程使用Prometheus查询语言的区间向量选择器,该选择器默认以当前时间为基准时间,选择过去一段时间inactivity_duration的采样值,再使用聚合操作符sum聚合值,指定保留请求函数的状态相应码code和函数名function_name。具体的Prometheus查询表达式如下所示。在具体处理逻辑中,合并所有HTTP状态码的指标,如状态码500、404、200等的指标出现次数累加,统计调用次数。
sum(rate(gateway_function_invocation_total{function_name="function_name", code=~".*"}["inactivity_duration"])) by (code, function_name)
3. 遍历函数,对于设置了缩容到零的标签(faas.scale.zero为true)的函数,查询MetricsMap,如果函数不活跃,获取它的副本数,触发一个函数缩容到零的事件,设置副本数为零。具体是调用FaaS API网关的REST接口,API Endpoint为/system/scale-function/function_name。
4. 每次执行后间隔reconcile_interval的时间,循环执行以上步骤1-3。