Nodejs也能Serverless?从0开始用Nodejs打造一个FaaS服务

本篇文章并不是教你怎么用阿里云、谷歌云等等云框架的FaaS服务,而是教你如何从0开始打造一个自己的FaaS服务。

受限于人力及成本原因,现在的FaaS服务基本上可以说是“大厂玩物”,而网上鲜有相关代码的实现,因此我才打算写一篇文章,和大家分享如何从0开始打造一个Nodejs的FaaS服务。

本篇文章中的项目tiny-node-faas已经上线并开源至GitHub,欢迎各位使用。
访问链接:http://www.shadowingszy.top/tiny-node-faas/index.html
源码地址:https://github.com/shadowings-zy/tiny-node-faas

一、背景及相关概念介绍

1-1、Serverless

Nodejs也能Serverless?从0开始用Nodejs打造一个FaaS服务_第1张图片
Serverless,直译就是无服务器,是指构建和运行不需要服务器管理的应用程序的概念。Serverless能够按需提供后端服务,用户可以直接编写和部署代码,而不必担心底层基础架构。

简单来说,如何判断一个服务是不是Serverless的呢?如果你在开发这个服务的时候,完全不知道“服务器多少”、“容器环境”等等和基础架构相关的东西的时候,那么这个服务就是Serverless的。

1-2、FaaS

FaaS是Function as a Service的缩写,可以简单理解为功能服务化。FaaS提供了一种服务碎片化的软件架构范式。FaaS可以让研发只需要关注业务代码逻辑,不再关注技术架构。

举个例子吧,如果我们要使用koa框架写一个hello world服务,我们得这样写:

const Koa = require('koa');
const app = new Koa();

const handler = async (ctx) => {
     
    ctx.body = 'hello world'
}

app.use(handler);
app.listen(8080,() => {
     
    console.log('8080端口已启动')
});

而如果使用FaaS服务,我们只需要关注下面这部分,其余的工作,比如服务创建、冷启动、负载均衡等等都由FaaS的提供方做了。

const handler = async (ctx) => {
     
    ctx.body = 'hello world'
}

1-3、为什么要做Nodejs的FaaS服务

之所以做Nodejs的FaaS服务,是因为有越来越多的开发者,以及越来越多的后台服务,选择使用Nodejs。

这其中当然有Nodejs本身“单线程异步非阻塞”的特性带给我们的简单直接的编程体验,也有一部分原因在于“前端全栈化”趋势会促使一部分前端工程师写后端代码逻辑。

而更值得关注的是,由于技术方向不同,不少前端开发工程师对运维、服务器的相关知识比较薄弱,因此为他们提供一个Nodejs的FaaS服务,能让其从运维中脱离出来,使开发者更聚焦于业务代码逻辑,是非常有前景的事情。

二、代码实现

2-1、vm模块

“如何实现Nodejs的FaaS服务”,这个问题可以换成下面这个问题:

如何才能在Nodejs中新建一个sandbox并在这个sandbox中执行指定的代码,并拿到返回值呢?

Nodejs实际上已经提供了这样一个模块——vm模块,下面是文档:
https://nodejs.org/api/vm.html

使用起来也很简单:

const vm = require('vm');

const code = 'console.log("hello world!")'

const sandbox = {
      console };
vm.createContext(sandbox);

const data = vm.runInNewContext(code, sandbox);

通过vm模块,我们就能在一个新的sandbox中执行JavaScript代码并拿到返回值了

2-2、整体架构

Nodejs也能Serverless?从0开始用Nodejs打造一个FaaS服务_第2张图片
如图所示,tiny-node-faas由四部分组成:
1、管理平台前端
2、函数管理功能
3、函数存储功能
4、函数执行功能

2、3、4三者则是FaaS服务中最重要的三个组成部分。

2-3、核心代码

const vm = require('vm')

const runFunction = async (code) => {
     
  let timer = null
  const result = await new Promise((resolve, reject) => {
     
    const sandbox = {
     
      require,
      console
    }

    try {
     
      timer = setTimeout(() => {
     
        reject(new Error('Execute function time out'))
      }, 10000)

      vm.createContext(sandbox)

      const data = vm.runInNewContext(code, sandbox)

      resolve(data)
    } catch (error) {
     
      reject(error)
    }
  }).catch((err) => {
     
    return err instanceof Error ? err : new Error(err.stack)
  })

  if (timer) {
     
    clearTimeout(timer)
    timer = null
  }

  return result
}

上面代码中的runFunction方法就是最核心的执行FaaS函数的方法,我们只需要传入code,即需要运行的代码,这个方法就会新建一个sandbox并运行代码,然后会将运行结果返回出来。

你可能感兴趣的:(前端,javascript,node.js,serverless)