基于阿里云函数计算FS 实现KOA项目部署 Serverless实践

背景
最近公司的客户有一个数据解析的需求,本来安排给后端工程师来做的,后来想想,像这些非核心项目需求,还是尽量不要动底层的项目逻辑,应该在业务层去解决。想了一下好像也不难,所以抽了一天时间就完成了需求,项目本身不难,就是用Koa框架写的一些解析方法,输出csv文件啥的。遇到比较大的坑竟然是在部署的时候。
本来想在服务器上丢一个docker上去,然后做一个编排,把代码和环境封装一下,后来想这种不是时长会用到,何必还要占用服务器资源呢,何不尝试使用serverless呢?
而且说到serverless,之前也做过两个小项目。是在腾讯的函数计算服务平台做的,当时感觉还是不错的,代码复制上去,简单的配置一下就可以跑起来了,而且按量收费,平时也不要管服务器的事儿,没想到这次在阿里的函数计算平台FC上遇到了不少的坑。不得不说,在用户体验上,还是腾讯更胜一筹。
这里记录了一下使用 Node + Koa 在阿里云上使用函数计算来部署项目的步骤和避坑指南。
项目核心代码
本项目的技术栈是基于 Node + Koa 来实现的中间件服务,请求的时候为了方便管理,封装了 Axios 作为请求拦截管理。
核心代码的坑点:
- 简单的项目,尽量使用 require(而不是import)
- 使用某些依赖的时候,看下最低兼容的Node版本。尽量选择node14以下的版本
- 如果以上两项都觉得烦,那么就乖乖的使用babel系列
项目结构
koa-demo
+ |- webpack.config.js
|- package.json
|- /dist
|- /src
|- index.js
|- xxx.js
|- config.js
开发热更新
不想每次修改了代码都手动重启项目,使用了nodemon作为代码监听更新npm i -D nodemon
监控node.js 源代码的变化和自动重启服务
启动项配置:
在packge.json中配置如下:
"scripts": {
"dev": "nodemon --exec babel-node index.js",
}
babel 系列模块的安装和配置
babel可以说是现代大前端不可或缺的ES版本兼容模块了,但是babel生态很繁杂,配置也很容易出错,这里记录一下我用的配置:
安装babel核心模块:
npm install -D @babel/core @babel/node @babel/preset-env babel-loader
// @babel/core核心模块
// @babel/node新版本的babel把node模块单独提出来了,需要单独安装
// @babel/preset-env 常用的配置脚本,支持"node": "current",将项目编译为当前node版本支持的语法
// babel-loader 是webpack打包时候使用的loader模块
配置使用:
创建.babelc文件,写入配置如下
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
部署准备
部署初探
实际了解了一下,在阿里云的函数计算FC服务中,上传代码有好几种不同的方式,
- 手动创建项目然后手动部署测试
- 使用serverless devs Cli来创建项目,然后cli 命令行上传部署
- 还可以使用云效中的任务流水线编排来部署项目
本文中主要介绍第二种用serverless devs Cli来部署项目
custom - runtime 还是原生Nodejs runtime?
据了解,阿里云为了可以兼容不语言的运行环境,支持custom - runtime,意思就是你可以上传一个自定义的运行环境然后通过命令行来启动这个自定义执行编译器来跑代码
同理,Nodejs runtime就是阿里云默认的一个Nodejs 引擎这个默认的引擎一般支持的版本不高,所以需要用户自己把代码编译出来才能跑,而且规定了端口必须使用9000。
那么选哪个呢?一般来说 Custom - runtime 比较简单(偷懒)和灵活,但是原生支持的 runtime 效率更高,不过需要预先编译。对于程序员来说,自然是效率高于灵活(偷懒)啦,所以本文介绍的是使用”云原生“来跑项目的方法
阿里云资源准备,环境初探
顾名思义,使用阿里云的函数计算服务,需要先去阿里云那边开通函数计算服务。
- 登陆阿里云,开通函数计算服务
- 确定自己有函数计算的使用授权,如果是RAM用户,需要让管理员开通函数计算的权限
- 尝试创建一个云函数,了解一下阿里云这边支持的最新支持的Node版本,目前默认是node12,还有一个阿里提供支持的node14版本(2022年4月份)。
- 点击右上角的用户头像,菜单栏选择 AccessKey,进入页面创建一个 AccessKey,记下 ID 和 Secret
serverless devs Cli
官方网站
serverless devs Cli是一个可以通过命令行部署代码的Cli工具,具体的源码在这里
安装Cli npm install @serverless-devs/s -g
s -v
验证一下是否安装成功
添加阿里云秘钥信息:s config add
选择目标云厂商,然后按回车。本文以Alibaba Cloud (alibaba)为例。
根据交互提示,设置相关密钥信息。输入完成后会提示Configuration successful
还有更详细的秘钥配置信息可以查看这里
Cli常用命令行
发布/部署:s deploy
可以尝试 用Koa 示例项目作为起点
配置完成了Cli后,可以使用以下步骤来简单的尝试一下Koa示例项目:
初始化一个 Koa 示例项目s init devsapp/start-koa -d start-koa
-d用于指定项目名称
进入项目目录 cd start-koa
直接部署项目 s deploy
如果没报错则会显示:... customDomains: xxx.xxxx.com
这个就是前部署的测试域名了
使用serverless Cli部署项目的几个注意事项
根据上面的实例代码,我们发现其实如果项目简单,迁移项目到函数计算其实还是很方便的。需要注意的有以下几点:
- 在项目的父级目录里,有一个 s.yaml的配置文件,是函数计算serverless的配置文件,需要根据需要来自行填写。具体的配置说明在这里
- 需要注意的是,s.yaml里面的执行参数可以写多个:
...
actions: # 自定义执行逻辑
pre-deploy: # 在deploy之前运行
- run: npm install --production && # 要运行的命令行
path: ./code # 命令行运行的路径
- run: npm run build # 要运行的命令行
path: ./code # 命令行运行的路径
- 项目目录下面的bootstarp文件是启动执行命令
#!/bin/bash
node dist/main.bundle.js
# 具体的打包输出文件地址应该按照实际打包的配置地址来填写
注意这里有个坑,如果项目中有使用了 cross-env NODE_ENV 这个环境变量,则去掉run: npm install --production
改为run: npm install
否则Cli会在run build时候报错找不到环境变量
用webpack打包koa项目
上文提到,我们需要使用阿里云”原生“的nodejs版本来部署生成环境,所以需要将项目编译出来,然后再部署到服务器。
由于nodejs 低版本的不支持es6的语法,所以这里会使用webpack将项目打包出去。具体的做法如下:
安装webpack cli:npm install webpack webpack-cli --save-dev
创建配置文件:webpack.config.js
配置说明:
const path = require('path')
module.exports = {
target: 'node', // 设置为node项目,重要!!!
mode: 'development', // 模式设置为开发模式,可以通过环境变量来使webpack打包时更换这个为 production
entry: path.join(__dirname, 'src', 'index.js'), // 入口文件
output: {
// 输出配置,这个就是bootstarp需要配置的打包文件名
filename: '[name].bundle.js',
// 打包地址
path: path.join(__dirname, 'dist')
},
module: {
rules: [
{
// 编译类型,js和jsx
test: /\.js|jsx$/,
// 使用babel-loader加载 babel 配置
use: {
loader: 'babel-loader'
},
// 只包含该目录
include: path.join(__dirname, 'src'),
// 排除node_modules这个目录
exclude: /node_modules/
}
]
},
resolve: {
// modules: 告诉webpack哪些目录需要搜索去匹配解析
modules: [path.join(__dirname, './src/index.js'), 'node_modules'],
// extensions: 告诉webpack这些后缀文件需要去搜索匹配
extensions: ['.js', '.json'],
alias: {
// 设置别名指向对应目录
'@': path.join(__dirname, '../src')
}
}
}
在更新 package.json 的启动项命令:
"dev": "nodemon --exec babel-node index.js",
"build": "webpack",
"start": "npm run build && nodemon dist/main.bundle.js",
部署到云函数FC
经过上面的配置和编译,终于到了部署的环节了。
- 先需要本地测试一下项目,比如使用nvm将node版本切换为node 12版本:
nvm use 12
- build 项目
npm run build
- 本地执行:
node dist/main.bundle.js
- 测试一下项目的各项接口,看看会不会报错
- 部署上线:
s deploy
,等待完成,出现项目地址后,点击测试
以上就是全部部署内容的工作了。
配置域名
- 进入阿里云后台的 函数计算FC 界面
- 点击 域名管理 页面,点击添加自定义域名
- 写入一个域名(一般都是二级域名)
- 复制页面中的 公网 CNAME 内容
- 打开域名管理页面,选择一个域名,点击域名解析
- 在域名解析页面中,点击添加解析,记录类型选择 CNAME,主机记录写刚刚上面写的二级域名地址前缀
- 在记录值栏 粘贴刚刚复制的 公网 CNAME 内容
- 保存即可