不懂就要问系列 - 02

Serverless 到底是什么 ?FaaS 和 BaaS 又是什么?

Serverless 到底是什么 ?FaaS 和 BaaS 又是什么?

Serverless 到底是什么 ?FaaS 和 BaaS 又是什么?

一种比较通俗的说法:你部署代码的时候再也不用关心服务器之类的问题。

一段相对严谨的说法:无服务器架构(Serverless architectures)是指一个应用大量依赖第三方服务(后端即服务,Backend as a Service,简称“BaaS”),或者把代码交由托管的、短生命周期的容器中执行(函数即服务,Function as a Service,简称“FaaS”)。现在最知名的 FaaS 平台是 AWS Lambda。把这些技术和单页应用等相关概念相结合,这样的架构无需维护传统应用中永远保持在线的系统组件。Serverless 架构的长处是显著减少运维成本、复杂度、以及项目起步时间,劣势则在于更加依赖平台供应商和现阶段仍有待成熟的支持环境。

后一种说法里提到了 BaaS 和 FaaS,这两个名词到底是什么意思呢?

  • BaaS: Backend as a Service,这里的Backend可以指代任何第三方提供的应用和服务,比如提供云数据库服务的Firebase和Parse,提供统一用户身份验证服务的Auth0和Amazon Cognito等。

  • FaaS: Functions as a Service,应用以函数的形式存在,并由第三方云平台托管运行,比如之前提到的AWS Lambda,Google Cloud Functions等。

相比于 Baas ,FaaS 还是比较抽象,下面有一个例子来说明

函数,往大了说可以是一个应用的main函数,往小了说也可以是一个简单的加法函数,那到底该如何理解FaaS中的函数呢?先来看张图。

左侧的Monolith即我们常说的单体应用,中间是微服务,右侧就是FaaS中的函数。

如同一个单体应用可以按业务模块拆分成多个微服务,一个微服务也可以按使用场景拆分成多个函数。

比如一个广告微服务,至少可以拆分出实时竞价、展示计数、报表查询等多个函数。

也就是说,FaaS中的函数和微服务中的API是同一粒度的。

但不同于API,在Serverless架构下,每个函数都是独立部署,按需执行。

在解释了 BaaS 和 FaaS 后,我们回过头来在用一个例子来解释 Serverless

举一个实际的例子,假设我要部署一个小系统,它的作用是从一个数据库中检索一个列表,并以 JSON 格式呈现出来。(因为我自己比较熟悉 Node,我们来写一个具体的实现)

var express = require('express');
var app = express();
app.get('/cats', (req, res) => {
//go get my cats
let cats = ["Luna","Robin","Cracker","Pig"];
res.json(cats);
});
app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'), () => {
console.log('Express running on http://localhost:' + app.get('port'));
});

整个代码是基于 Express 框架来实现的,所以为了实现这个 API,我必须加载 Express,但重点在下面:

  • 首先,我需要一种设置和处理路由的方法,以便我知道何时显示路由 cats。换句话说,我要知道 /cats 是否被请求,而不是别的请求。

  • 我必须启动一个 Web 服务器才能响应这些 API 调用。 虽然 Express 使这个变得很容易,但是我还是要做这一步。

  • 我要处理一个请求和一个响应来处理客户端 API 调用。Express 再次简化了这个流程,但是现在我的逻辑和 HTTP 有着密切的联系。

所以总的来说还不错。我可以在几分钟内运行起来。但是我需要部署它。

  • 首先我找到一个主机。例如美团云,哈哈,在这些主机上能够部署我的 Node 代码,并在几分钟内启动并运行。

  • 作为这个过程的一部分,我必须考虑应用程序的使用情况,并对 CPU,内存等进行一些选择。

那么云服务带来的改变是什么呢?我可以几秒钟内在云服务上的机器里部署好 Node 环境。这里还是涉及到了服务器。我们还是需要设置它(不管容易与否)。

所以在这些场景下,不管怎样你都需要设置服务器。

现在让我们回过头来看看 serverless。使用相同的用例,下面是我的代码:

function main(args) {
//go get my cats
let cats = ["Luna", "Robin", "Cracker", "Pig"];
return { cats: cats};
}

就这样。实现业务逻辑的代码是我唯一需要关心的。

请注意,这个函数需要一个 args 参数,这是 OpenWhisk 处理参数的方式。在 Lambda 或谷歌云功能中可能会有所不同,所以有一些依赖平台的代码。

部署这些只需要运行命令行将其添加到 OpenWhisk 中,类似的程序可以用于其他 serverless 平台。所以最后…

我只关心业务逻辑(获取 /cats

我不关心路由,我的平台会告诉我 cats 是可用的

我没有绑定到 HTTP 模型了。我可以使用这个例子作为 serverless 平台每天运行的计划任务,甚至不考虑网络。

最后,我仍然在做同样的事情 — 使我的业务逻辑可用。但是我并不关心与网络访问相关的其它事情。

换句话说,我不关心服务器。