迁移猿文档到 Severless 架构

背景

好早前就知道了 Serverless 架构,近日发现阿里云支持了函数计算,便决定将猿文档的后端服务进行迁移。

此前,猿文档的后端服务基于 Node.js,采用 egg.js 框架,运行于 docker 中,购买的是阿里云的云服务器 ECS。之所以决定此次迁移是由于以下几点原因:

  • 按使用收费:目前猿文档的请求量并不大,不存在高频请求的情况,阿里云函数计算的免费额度够用。
  • 功能简单:猿文档只有三个接口,方便迁移。
  • 维护性:使用无服务器架构只需要部署一个个函数,简单易用。

进行

阿里云函数计算可以在这里了解函数计算文档中心

原 3 个接口可以很方便的写成三个函数,基本格式如下:

module.exports.handler = function (request, response, context) {
  const queries = request.queries;
  // ...
  const res = {
    message: 'ok',
    code: 0,
  };
  response.setHeader('Content-Type', 'application/json');
  response.setStatusCode(200);
  response.send(JSON.stringify(res));
};

部署使用 fcli 工具。进入 fcli shell 后基本操作如下:

>>> ls  # 查看服务列表
>>> cd yuanwendang  # 进入服务
>>> ls  # 查看函数列表
>>> mkf doc-entry -h entry.handler -d ./doc-entry -t nodejs8  # 新建函数
>>> upf doc-entry -h entry.handler -d ./doc-entry -t nodejs8  # 更新函数

在阿里云的管理控制台中会将服务中的函数清晰的呈现出来:

其中 public 函数是用来响应静态文件请求的:

'use strict';
const fs = require('fs');
const util = require('util');
const path = require('path');
const mime = require('mime-types');

const stat = util.promisify(fs.stat);
const readFile = util.promisify(fs.readFile);

const send404 = (response) => {
  response.setHeader('Content-Type', 'text/plain');
  response.setStatusCode(404);
  response.send('404 Not Found');
};

module.exports.handler = function (request, response, context) {
  const reqPath = request.path;
  const filePath = path.join(__dirname, reqPath);
  stat(filePath)
    .then(stats => {
      if (stats.isFile()) {
        readFile(filePath)
          .then(data => {
            response.setStatusCode(200);
            const contentType = mime.lookup(filePath) || 'application/octet-stream';
            response.setHeader('Content-Type', contentType);
            response.send(data);
          })
          .catch(err => {
            console.error(err);
            send404(response);
          });
      } else {
        send404(response);
      }
    })
    .catch(err => {
      send404(response);
    })
};

每一个函数都可以在控制台中编辑,调试:

Fn project

Fn项目是一个开源的容器本地无服务器平台,您可以在任何地方运行 - 任何云或内部部署。它易于使用,支持多种编程语言,并且是可扩展和高性能的。