架构测评-OpenFaaS是私有云FaaS的解决方案吗?

微服务不是一种发明,而是一种趋势,一种总结现实世界工作方式得到的模式。 其本质是一种分治思想。

What

FaaS: Functions as a Service

在应用开发过程中,随着业务复杂度的提升,以及快速迭代的需求,微服务以及变得十分主流。并且推进提升了平台、软件、硬件、管理体系等各方面,以便更好的支持微服务架构。

那么按照这个趋势继续推演,借助云平台提供的基础支撑能力,最细粒度不应该是一个服务,而应该是一个方法函数。这样才能将职责划分、动态调度发挥到极致。

所以FaaS来到了历史舞台。我觉得FaaS是一种更极端的微服务,注意是更极端,而不是更极致。

Why

想象一个场景,产品经理提出一个需要获取服务端当前时间的需求,我们需要创建工程项目->编写方法代码->编译打包->测试发布->被外部调用

  1. 如果请求量过大,需要申请增加机器,重新发布。
  2. 如果请求量过小,但是为了保障高可用,至少需要部署2台机器。这时就造成了资源的浪费。

同样的场景,也可能是这样一番景象:接到需求后,打开IDE或者浏览器编写方法代码,提交之后就可以被外部调用。

当然这是开发视角,在看不见的角落还需要有人完成 stateless、CICD、持久化、技术异构、监控、弹性、扩展 等各方面的支撑工作。

而 OpenFaaS 的目标就是让这个过程变得足够简单。

OpenFaaS

OpenFaaS® makes it easy for developers to deploy event-driven functions and microservices to Kubernetes without repetitive, boiler-plate coding. Package your code or an existing binary in a Docker image to get a highly scalable endpoint with auto-scaling and metrics.

先来看一下OpenFaaS的图标,应该看得出来他和docker有着密不可分的关系。

openfaas_00

(话说。。。 这不是一个翻车的鲸鱼么)

安装

通过Helm安装后可以看到有如下 Deployment 组件,功能会在后文描述。

openfaas_01

使用三方Function

OpenFaaS提供了UI页面,可以通过浏览器管理Functions,并且提供了Function Store 用于快速使用他人发布的Function。

比如 通过 Store 寻找三方提供的二维码生成Function

openfaas_02

在页面中通过 invoke 按钮可以调用相关函数,并获得返回结果。

openfaas_03

这背后的逻辑是,找到已经发布的Function docker镜像,在k8s中完成部署,并通过Gateway路由到相关方法并返回执行结果。所以也可以直接通过http api 进行调用。

发布自定义Function

OpenFaas 提供了功能全面的CLI工具,可以通过 curl or brew 安装

1
curl -sSL https://cli.openfaas.com | sh

or brew

1
brew install faas-cli

查看官方提供的模板

openfaas_04

这里以java为例,开发一个java11的Function

openfaas_05

打开生成的项目,在 Handler 类中完成相关处理逻辑

openfaas_06

完成docker镜像构造

openfaas_07

接下来要度过一个感人的构造时间

openfaas_08

还有同样感人的镜像大小

openfaas_09

如果设置了auth控制,则需要完成登陆认证

openfaas_10

发布至服务,需要确认本机拥有k8s机器操作权限

openfaas_11

此时可以在k8s中查看到java-function 的 Deployment,等到服务启动成功后,就可以通过UI界面或者url接口的方式被调用

openfaas_11_1

openfaas_12

如果需要修改Function逻辑,需要重复执行上述步骤。但是因为已经下载过基础镜像,修改之后再次打包的速度会提升很多。

openfaas_13

上述过程可以通过CICD流程自动完成,如: gitlab、Jenkins等

监控

官方提供了Grafana模板(3526),方便快速搭建起一个Dashboard

openfaas_14

openfaas_15

但是只有最基础的内容,还需要自己设置更多的指标项。

弹性伸缩

Prometheus 记录Function调用记录, AlertManager 通过 Prometheus 统计单位时间内QPS,如果超过阈值,则调用Gateway提供的Scale接口进行扩容,并指定过期时间。
如果超过过期时间,则自动进行缩容。
默认容量为1,甚至可以设置为0,以确保当有请求过来时,才会启动相关Function,以避免资源浪费。

openfaas_16

异步Function

异步Function会在Gateway中维护一个请求队列,可以外接第三方的消息中间件,如Kafka。Gateway会依次消费处理,并根据设置的Callback Url进行回调通知

openfaas_17

openfaas_17_1

相关实现代码

openfaas_18

How

服务发现

Gateway通过轮训的方式发现指定namespace下的所有function

openfaas_19

并通过Function名称寻找对应的Deployment转发路由调用

服务注入

以java为例其实是在模板中内置接口,然后通过SPI的方式完成服务注入

openfaas_20

entrypoint 会启动一个http服务响应Gateway路由而来调用

openfaas_21

感受

  1. 如果已经有了一套配合k8s的CICD流程,就会发现整个过程并没有节省什么,反而增加了很多限制。
  2. 并没有提供状态应用、持久化等方便的实现或建议。
  3. 已经到了代码层面,又提供了UI界面,为什么没有接口文档功能呢?
  4. java 经历打jar包、docker镜像等过程,大小和时间都不够友好,当然这可能是java的问题,但是有更优方案。