当前位置: 首页 > 工具软件 > faas > 使用案例 >

Faas无服务器架构杂谈

庞瀚
2023-12-01

FAAS原理白话就是,用户提交一段函数代码(如js代码),我们后台把代码拼接为dockerfile(根据用户的函数语言,自动组装(如js代码需要js环境,nginx),后台打一个镜像,然后k8s集群根据用户的配置需求,跑这个docker镜像。用户删除函数,直接把镜像销毁。

以下为开源FAAS:Openwhisk的基本使用

Openwhisk是属于Apache基金会的开源Faas计算平台,由IBM在2016年公布并贡献给开源社区。IBM Cloud本身也提供完全托管的OpenWhisk Faas服务IBM Cloud Function。从业务逻辑来看,OpenWhisk同AWS Lambda一样,为用户提供基于事件驱动的无状态的计算模型,并直接支持多种编程语言。
OpenWhisk特点:
• 高性能,高扩展性的分布式FaaS计算平台
• 函数的代码及运行时全部在Docker容器中运行,利用Docker engine实现FaaS函数运行的管理、负载均衡、扩展.
• OpenWhisk所有其他组件(如:API网关,控制器,触发器等)也全部运行在 Docker容器中。这使得OpenWhisk全栈可以很容易的部署在任意IaaS/PaaS平台上。
• 相比其他FaaS实现(比如OpenFaaS),OpenWhisk更像是一套完整的Serverless 解决方案,除了容器的调用和函数的管理,OpenWhisk 还包括了用户身份验证/鉴权、函数异步触发等功能。
目前支持的语言: Nodejs, Python, Java, php, Ruby, Go, Rust, dotnet, Ballerina, blackBoxes。
安装

整个安装需要提前安装java跟nodejs。
• 安装java

下载JDK

http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

将JDK安装包上传到服务器上并解压

$ tar -zxvf jdk-8u171-linux-x64.tar.gz
#切换到当前用户目录下面,编辑配置文件
$ cd ~
$ vim .bash_profile

在.bash_profile文件最后添加

JAVA_HOME=/home/tomcat/jdk1.8.0_171
CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/jre/lib
PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin

export JAVA_HOME CLASSPATH PATH

#验证

$ java -version

• 安装nodejs

下载Node.js安装包

wget https://nodejs.org/dist/v10.15.3/node-v10.15.3-linux-x64.tar.xz

#解压文件

tar xvf node-v10.15.3-linux-x64.tar.xz

创建软链接

ln -s /home/node-v10.15.3-linux-x64.tar.xz/bin/node /usr/local/bin/node
ln -s /home/node-v10.15.3-linux-x64.tar.xz/bin/npm /usr/local/bin/npm

查看node, npm版本

node -v
npm -v

如果成功,则安装完成

• 编译openwhisk

如果没有代码,可以从本地上传或从git clone下载

yum install git

git clone下来

git clone https://github.com/apache/incubator-openwhisk.git openwhisk

切换到openwhisk目录,运行下面命令

$ ./gradlew :core:standalone:build

• 配置OpenWhisk Cli工具:下载https://github.com/apache/openwhisk-cli

上传到服务器解压, 解压

设置API HOST

wsk property set --apihost http://172.17.0.1:3233

设置auth

wsk property set --auth 789c46b1-71f6-4ed5-8c54-816aa4f8c502

可以通过以下命令获取当前的auth

wsk property get --auth

• 在.\bin目录下面会有相应的可执行文件。

java -jar openwhisk-standalone.jar

会有如下输出:

        ____      ___                   _    _ _     _     _
       /\   \    / _ \ _ __   ___ _ __ | |  | | |__ (_)___| | __
  /\  /__\   \  | | | | '_ \ / _ \ '_ \| |  | | '_ \| / __| |/ /
 /  \____ \  /  | |_| | |_) |  __/ | | | |/\| | | | | \__ \   <
 \   \  /  \/    \___/| .__/ \___|_| |_|__/\__|_| |_|_|___/_|\_\
  \___\/ tm           |_|
    

Running pre flight checks ...

Local Host Name: 172.17.0.1
Local Internal Name: 172.17.0.1

[  OK   ] 'docker' cli found. (Docker version 19.03.6, build 369ce74a3c)
[  OK   ] 'docker' version 19.3.6 is newer than minimum supported 18.3.0
[  OK   ] 'docker' is running.
[  OK   ] 'wsk' cli found. (2019-09-23T17:46:38.323+0000)
[ WARN  ] Configure wsk via below command to connect to this server as [guest]

wsk property set --apihost 'http://172.17.0.1:3233' --auth '23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP'
[  OK   ] Server port [3233] is free

服务起来后设置提示的命令:设置apihost和auth

wsk property set --apihost 'http://172.17.0.1:3233' --auth '23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP'

• 运行Hello world

创建hello.js文件

/**
 * Hello world as an OpenWhisk action.
 */
function main(params) {
    var name = params.name || 'World';
    return {payload:  'Hello, ' + name + '!'};
}

创建action

$ wsk action create hellotest hello.js
ok: created action hellotest
$ wsk action invoke hellotest --result
{
    "playload": "hello world"
}

系统流程

先介绍一下 OpenWhisk 中从事件触发到函数执行完毕的流程。 OpenWhisk 中,代码是基于事件(Event)触发的。事件产生于事件源(feed),可以用于触发函数的事件多种多样:可以是IoT设备传感器发出的信号,可以是一个 Github repo的push,也可以是最简单的一个前端HTTP 请求。事件与对应的函数代码,通过规则(Rule)绑定。通过匹配事件对应的规则,OpenWhisk会触发对应的行为(Action)。值得注意的是,多个Action 可以串联,完成复杂的操作。
整体架构

参考链接:https://github.com/apache/openwhisk/blob/master/docs/about.md

  1. 面向用户的REST API(Nginx): OpenWhisk 的核心系统通过Rest API 接收函数触发和函数的CRUD请求。如一个函数触发的POST请求格式如下···POST /api/v1/namespaces/$userNamespace/actions/myAction ···此处的nginx 服务器主要用于接收 HTTPS 请求(SSL termination),并将处理后的 HTTP 请求直接转发给控制器(Controller).
  2. 控制器(Controller, 真正进入系统): 真正开始处理请求的地方。控制器是用 Scala 语言实现的,并提供了对应的 REST API,接收 Nginx 转发的请求。Controller 分析请求内容,进行下一步处理。
  3. CouchDB(身份验证和鉴权):控制器首先需要验证用户的身份和权限。用户的身份信息(credentials)保存在CouchDB的用户身份数据库(subjects database)中。验证无误后,控制器进行下一步处理。
  4. CouchDB(得到对应的Action的代码及配置): 确认用户的身份后,控制器需要从 CouchDB中读取将要被触发的函数(OpenWhisk将要执行的代码片段抽象成为 Action,为了简便,此处直接称之为函数)。函数对应的数据存储在CouchDB的whisk 数据库,主要包含要被执行的代码、默认参数、被执行代码的权限、及CPU/内存使用限制。
  5. Consul和负载均衡:到了这一步,控制器已经有了触发函数所需要的全部信息,在将数据发送给触发器(Invoker)之前,控制器需要和Consul确认,从Consul 获取处于空闲状态的触发器的地址。Consul 是一个开源的服务注册/发现系统,在 OpenWhisk中Consul负责记录跟踪所有触发器的状态信息。当控制器向Consul发出请求,Consul从后台随机选取一个空闲的触发器信息,并返回。
  6. 触发请求送进Kafka: Kafka 充当了Controller和Invoker之间的缓存,当后端 Invoker 负载过大,没有及时处理Kafka数据流中的请求时,Controller 依然可以将请求送入Kafka,无需阻塞当前线程。同时所有送进Kafka 的请求消息都会被以log的形式的形式保存在文件系统中,即使系统瘫痪,已经由 Controller发出的请求也不会丢失。
  7. 触发器运行用户代码: 触发器从对应的 Kafka topic 中接收控制器传来的请求,并执行响应代码。OpenWhisk 的触发器是构建在 Docker 之上的,每一个函数触发都运行在一个独立的 Docker 容器之内.
  8. CouchDB 保存运行结果: 触发器执行结果最终会被保存在 CouchDB 中的 whisk 数据库里, 保存的格式如下:
{
   "activationId": "31809ddca6f64cfc9de2937ebd44fbb9",
   "response": {
       "statusCode": 0,
       "result": {
           "hello": "world"
       }
   },
   "end": 1474459415621,
   "logs": [
       "2016-09-21T12:03:35.619234386Z stdout: Hello World"
   ],
   "start": 1474459415595,
}

保存结果包括用户函数的返回值,及日志记录。对异步触发用户,可以通过步骤6中返回的activationID取回函数运行结果。同步触发的的结果和异步触发一样保存在 CouchDB里,控制器在得到触发结束的确认后,从CouchDB 中取得运行结果,直接返回给用户。

 类似资料: