返回介绍

三、Serverless Framework 部署项目实战

发布于 2024-01-31 23:58:26 字数 39446 浏览 0 评论 0 收藏 0

3.1 Serverless Framework 简介及应用场景

  • Serverless Framework 是 Serverless 公司推出的一个开源的 Serverless 应用开发框架
  • Serverless Framework 是 由 Serverless Framework Plugin 和 Serverless Framework Components 组成
  • Serverless Framework Plugin 实际上是一个函数的管理工具,使用这个工具,可以很轻 松的部署函数、删除函数、触发函数、查看函数信息、查看函数日志、回滚函数、查看函数 数据等

Serverless Framework Components 可以看作是一个组件集,这里面包括了很多的 Components,有基础的 Components,例如 cos、scf、apigateway 等,也有一些拓展的 Components,例如在 cos 上拓展出来的 website,可以直接部署静态网站等,还有一些框 架级的,例如 Koa,Express 等

Serverless Framework 应用场景

上面既然介绍了云函数和 serverless 的区别,现在我们介绍下什么场景下需要使用 serverless ,而不是使用云函数,其实在实际开发过程中,我们都是使用 serverless 而不去使用云函数,毕竟云函数的使用场景受限,或者说比较基础。打一个简单的比方,在写 js 操作 dom 的时候,你会选择用原生 js 还是会使用 jquery 一样的比喻

基于云函数的命令行开发工具

通过 Serverless Framework ,开发者可以在命令行完成函数的开发、部署、调试。还可以结合前端服务、 API 网关、数据库等其它云上资源,实现全栈应用的快速部署。

传统应用框架的快速迁移

Serverless Framework 提供了一套通用的框架迁移方案,通过使用 Serverless Framework 提供的框架组件( Egg/Koa/Express 等, 更多的框架支持可以参考 ),原有应用仅需几行代码简单改造, 即可快速迁移到函数平台。同时支持命令行与控制台的开发方式。

Serverless Framework 支持的平台

https://github.com/serverless/serverless/tree/master/docs/providers

3.2 Serverless Components 支持组件列表

基础组件

高阶组件

3.3 sls 部署 egg 项目

egg 框架中默认已经配置好了静态资源,我们可以直接访问。要注意的是 serverless 服务器 上面只有根目录的 tmp 目录有写入权限,所以需要配置 egg 日志存储的目录。默认创建好 项目以后有如下配置。

// config/config.default.js 

module.exports = (appInfo) => {
  // 
  return {
    ...,
    rundir: '/tmp',
    logger: {
      dir: '/tmp'
    },
  }
}

控制台创建部署-模板部署

  1. 登录控制台 https://console.cloud.tencent.com/sls
  2. 单击新建应用,选择 Web 应用>Egg 框架,如下图所示:

  1. 单击“下一步”,完成基础配置选择。

  1. 上传方式,选择示例代码直接部署,单击完成,即可开始应用的部署。
  2. 部署完成后,您可在应用详情页面,查看示例应用的基本信息,并通过 API 网关生成的访问路径 URL 进行访问,查看您部署的 Egg 项目。

控制台创建部署-自定义部署(推荐)

如果除了代码部署外,您还需要更多能力或资源创建,如自动创建层托管依赖、一键实现静态资源分离、支持代码仓库直接拉取等,可以通过应用控制台,完成 Web 应用的创建工作

初始化项目

mkdir egg-example && cd egg-example
npm init egg --type=simple
npm i

部署上云

接下来执行以下步骤,对本地已创建完成的项目进行简单修改,使其可以通过 Web Function 快速部署,对于 Egg 框架,具体改造说明如下:

  • 修改监听地址与端口为 0.0.0.0:9000
  • 修改写入路径,serverless 环境下只有 /tmp 目录可读写。
  • 新增 scf_bootstrap 启动文件。

1. (可选) 配置 scf_bootstrap 启动文件

您也可以在控制台完成该模块配置。

在项目根目录下新建 scf_bootstrap 启动文件,在该文件添加如下内容(用于配置环境变量和启动服务,此处仅为示例,具体操作请以您实际业务场景来调整):

#!/var/lang/node12/bin/node

'use strict';

/**
 * docker 中 node 路径:/var/lang/node12/bin/node
 * 由于 serverless 函数只有 /tmp 读写权限,所以在启动时需要修改两个环境变量
 * NODE_LOG_DIR 是为了改写 egg-scripts 默认 node 写入路径(~/logs)-> /tmp
 * EGG_APP_CONFIG 是为了修改 egg 应有的默认当前目录 -> /tmp
 */

process.env.EGG_SERVER_ENV = 'prod';
process.env.NODE_ENV = 'production';
process.env.NODE_LOG_DIR = '/tmp';
process.env.EGG_APP_CONFIG = '{"rundir":"/tmp","logger":{"dir":"/tmp"}}';

const { Application } = require('egg');

// 如果通过层部署 node_modules 就需要修改 eggPath
Object.defineProperty(Application.prototype, Symbol.for('egg#eggPath'), {
  value: '/opt',
});

const app = new Application({
  mode: 'single',
  env: 'prod',
});

app.listen(9000, '0.0.0.0', () => {
  console.log('Server start on http://0.0.0.0:9000');
});

新建完成后,还需执行以下命令修改文件可执行权限,默认需要 777 或 755 权限才可正常启动。示例如下:

chmod 777 scf_bootstrap

2. 控制台上传

您可以在控制台完成启动文件 scf_bootstrap 内容配置,配置完成后,控制台将为您自动生成 启动文件,和项目代码一起打包部署

启动文件以项目内文件为准,如果您的项目里已经包含 scf_bootstrap 文件,将不会覆盖该内容。

查看函数,修改代码查看日志等

高级配置管理

您可在“高级配置”里进行更多应用管理操作,如创建层、绑定自定义域名、配置环境变量等。

HTTP 组件方式部署(推荐)

目前推荐使用 web 函数,也就是 HTTP 组件 ,现在所有的 serverless web 应用都是基于 component: http 组件的。

通过 Serverless FrameworkHTTP 组件 ,完成 Web 应用的本地部署

前提条件

已开通服务并完成 Serverless Framework 的 权限配置

# 初始化 egg 项目

serverless init eggjs-starter(可以替换成 sls registry 已有的模板) --name egg-example
# 编写完善配置文件 serverless.yml
# https://github.com/serverless-components/tencent-http/blob/master/docs/configure.md
app: egg-example-fa63d20e9 # 应用名称
component: http # http 组件
name: egg-demo # 实例名称
inputs:
  region: ap-guangzhou # 云函数所在区域
  src: # 部署当前目录下的文件代码,并打包成 zip 上传到 bucket 上
    src: ./ # 当前目录
    exclude: # 被排除的文件或目录
      - .env
      - 'node_modules/**' # 忽略 node_modules,在控制台 WEBIDE 开启安装依赖
  # src: # 在指定存储桶 bucket 中已经存在了 object 代码,直接部署
  #   bucket: bucket01 # bucket name,当前会默认在 bucket name 后增加 appid 后缀, 本例中为 bucket01-appid
  #   object: cos.zip  # bucket key 指定存储桶内的文件
  faas: # 函数配置相关
    runtime: Nodejs12.16 # 运行时
    # 支持的框架查看 https://cloud.tencent.com/document/product/1154/59447#framework
    framework: egg # #选择框架,此处以 egg 为例 
    name: ${name} # 云函数名称,通过变量形式获取 name 的值
    timeout: 60 # 超时时间,单位秒
    memorySize: 512 # 内存大小,默认 512 MB
    # layers:
    #   - name: layerName #  layer 名称
    #     version: 1 #  版本
    environments: #  配置环境变量,同时也可以直接在 scf 控制台配置 
        - key: NODE_ENV
          value: production
    # vpc: # 私有网络配置
    #   vpcId: 'vpc-xxx' # 私有网络的 Id
    #   subnetId: 'subnet-xxx' # 子网 ID
    # tags:
    #   - key: tagKey
    #     value: tagValue
  apigw: # http 组件会默认帮忙创建一个 API 网关服务
    isDisabled: false # 是否禁用自动创建 API 网关功能
    # id: service-xx # api 网关服务 ID,不填则自动新建网关
    name: serverless # api 网关服务名称
    api: # 创建的 API 相关配置
      cors: true #  允许跨域
      timeout: 30 # API 超时时间
      name: apiName # API 名称
      qualifier: $DEFAULT # API 关联的版本
    protocols:
      - http
      - https
    environment: test
    # tags:
    #   - key: tagKey
    #     value: tagValue
    # customDomains: # 自定义域名绑定
    #   - domain: abc.com # 待绑定的自定义的域名
    #     certId: abcdefg # 待绑定自定义域名的证书唯一 ID
    #     # 如要设置自定义路径映射,(customMap = true isDefaultMapping = false) 必须两者同时出现 其余情况都是默认路径
    #     customMap: true
    #     isDefaultMapping: false
    #     # 自定义路径映射的路径。使用自定义映射时,可一次仅映射一个 path 到一个环境,也可映射多个 path 到多个环境。并且一旦使用自定义映射,原本的默认映射规则不再生效,只有自定义映射路径生效。
    #     pathMap:
    #       - path: /
    #         environment: release
    #     protocols: # 绑定自定义域名的协议类型,默认与服务的前端协议一致。
    #       - http # 支持 http 协议
    #       - https # 支持 https 协议
    # app: #  应用授权配置
    #   id: app-xxx
    #   name: app_demo
    #   description: app description

全部配置详细查看 https://github.com/serverless-components/tencent-http/blob/master/docs/configure.md

部署

创建完成后,在根目录下执行 sls deploy 进行部署,组件会根据选择的框架类型,自动生成 scf_bootstrap 启动文件进行部署

我们也可以在项目跟目录自己创建启动文件 scf_bootstrap ,然后 chmod 777 scf_bootstrap

// scf_bootstrap
#!/var/lang/node12/bin/node

/**
 * docker 中 node 路径:/var/lang/node12/bin/node
 * 由于 serverless 函数只有 /tmp 读写权限,所以在启动时需要修改两个环境变量
 * NODE_LOG_DIR 是为了改写 egg-scripts 默认 node 写入路径(~/logs)-> /tmp
 * EGG_APP_CONFIG 是为了修改 egg 应有的默认当前目录 -> /tmp
 */

process.env.EGG_SERVER_ENV = 'prod';
process.env.NODE_ENV = 'production';
process.env.NODE_LOG_DIR = '/tmp';
process.env.EGG_APP_CONFIG = '{"rundir":"/tmp","logger":{"dir":"/tmp"}}';

const { Application } = require('egg');

// 如果通过层部署 node_modules 就需要修改 eggPath
Object.defineProperty(Application.prototype, Symbol.for('egg#eggPath'), {
  value: '/opt',
});

const app = new Application({
  mode: 'single',
  env: 'prod',
});

app.listen(9000, '0.0.0.0', () => {
  console.log('Server start on http://0.0.0.0:9000');
});
# 微信扫码即可 
# 微信扫码授权部署有过期时间,如果想要持久授权,请参考账号配置(https://cloud.tencent.com/document/product/1154/45874#account)
# 当前默认支持 CLI 扫描二维码登录,如您希望配置持久的环境变量/密钥信息,也可以本地创建 .env 文件:
# 在 .env 文件中配置腾讯云的 SecretId 和 SecretKey 信息并保存。
# API 密钥管理 https://console.cloud.tencent.com/cam/capi
# .env
#TENCENT_SECRET_ID=123
#TENCENT_SECRET_KEY=123

sls deploy

注意:由于启动文件逻辑与用户业务逻辑强关联,默认生成的启动文件可能导致框架无法正常启动,建议您根据实际业务需求,手动配置启动文件, 详情参考各框架的部署指引文档

如果部署过程遇到问题不好排除,如以下问题:

来到控制台创建项目

在控制台安装依赖包

我们在 sls deploy 忽略了 node_modules ,因此需要在控制台安装依赖

访问应用

到控制台查看

删除应用

sls remove

使用 Layer 来减小项目文件大小

随着项目复杂度的增加, deploy 上传会变慢。所以,让我们再优化一下,在项目根目录创建 layer/serverless.yml

# layer/serverless.yml
# https://cloud.tencent.com/document/product/1154/51133
# https://github.com/serverless-components/tencent-layer/blob/master/docs/configure.md

#应用组织信息(可选)
app: egg-demo
stage: dev

#组件信息
component: layer
name: egg-demo-layer # 层名称 必须

# 组件参数配置,根据每个组件,实现具体的资源信息配置
inputs:
 name: ${name} # 名称跟上面一致即可
 region: ap-guangzhou # 地区 必须
 src: ../node_modules #需要上传的目标文件路径 必须 
  # src: # 代码路径。与 object 不能同时存在。
  #   src: ./node_modules
  #   targetDir: /node_modules
  #   exclude:   # 被排除的文件或目录 不包含的文件或路径, 遵守 glob 语法
  #     - .env
  #     - node_modules
  # src:
  # bucket 名称。如果配置了 src,表示部署 src 的代码并压缩成 zip 后上传到 bucket-appid 对应的存储桶中;如果配置了 object,表示获取 bucket-appid 对应存储桶中 object 对应的代码进行部署。
  #   bucket: layers
  #   object: sls-layer-test-1584524206.zip # 部署的代码在存储桶中的路径。
  #   exclude:   # 被排除的文件或目录
  #     - .env
  #     - node_modules
 runtimes: # 层支持的运行环境
   - Nodejs12.16 
 description: layer description # 否 描述

创建后可见层对应信息

我们也可以在控制台新建层绑定到对应的函数即可

控制台上传层有大小限制

文件夹支持 250M

修改以上项目下的 serverless.yml 加入层配置

回到项目根目录,调整一下根目录的 serverless.yml

# 编写完善配置文件 serverless.yml
# https://github.com/serverless-components/tencent-http/blob/master/docs/configure.md
app: egg-example-fa63d20e9 # 应用名称
component: http # http 组件
name: egg-demo # 实例名称
inputs:
  region: ap-guangzhou # 云函数所在区域
  src: # 部署当前目录下的文件代码,并打包成 zip 上传到 bucket 上
    src: ./ # 当前目录
    exclude: # 被排除的文件或目录
      - .env
      - "node_modules/**" # deploy 时排除 node_modules [需要注意] 使用 layer 的 node_modules
  faas: # 函数配置相关
    runtime: Nodejs12.16 # 运行时
    # 支持的框架查看 https://cloud.tencent.com/document/product/1154/59447#framework
    framework: egg # #选择框架,此处以 egg 为例 
    name: ${name} # 云函数名称,通过变量形式获取 name 的值
    timeout: 60 # 超时时间,单位秒
    memorySize: 512 # 内存大小,默认 512 MB
    # 加入层配置 引用格式请参考 变量引用说明 https://github.com/AprilJC/Serverless-Framework-Docs/blob/main/docs/%E5%87%BD%E6%95%B0%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91/%E6%9E%84%E5%BB%BA%E5%BA%94%E7%94%A8.md
    layers: 
      - name: ${output:${stage}:${app}:${name}-layer.name} # 配置对应的 layer
        version: ${output:${stage}:${app}:${name}-layer.version} # 配置对应的 layer 版本
    environments: #  配置环境变量,同时也可以直接在 scf 控制台配置 
        - key: NODE_ENV
          value: production
    tags: # 标签
      - key: tagKey
        value: tagValue
  apigw: # http 组件会默认帮忙创建一个 API 网关服务
    isDisabled: false # 是否禁用自动创建 API 网关功能
    # id: service-xxx # api 网关服务 ID,不填则自动新建网关
    name: serverless # api 网关服务名称
    api: # 创建的 API 相关配置
      cors: true #  允许跨域
      timeout: 30 # API 超时时间
      name: apiName # API 名称
      qualifier: $DEFAULT # API 关联的版本
    protocols:
      - http
      - https
    environment: test

排除 node_modules

exclude: # 被排除的文件或目录
    - .env
    - node_modules/** # deploy 时排除 node_modules [需要注意] 使用 layer 的 node_modules

配置层

引用格式请参考 变量引用说明 https://github.com/AprilJC/Serverless-Framework-Docs/blob/main/docs/%E5%87%BD%E6%95%B0%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91/%E6%9E%84%E5%BB%BA%E5%BA%94%E7%94%A8.md

layers: 
    - name: ${output:${stage}:${app}:${name}-layer.name} # 配置对应的 layer
    version: ${output:${stage}:${app}:${name}-layer.version} # 配置对应的 layer 版本

通过配置层 layer,代码和 node_modules 分离, sls deploy 更快

接着执行命令 sls deploy --target=./layer 部署层,然后再次部署 sls deploy 看看速度应该更快了

每次 node_modules 改变都需要

  • 执行 sls deploy --target=./layer 部署层, 更新 node_modules
  • 执行 sls deploy 重新部署

layer 的加载与访问

layer 会在函数运行时,将内容解压到 /opt 目录下,如果存在多个 layer ,那么会按时间循序进行解压。如果需要访问 layer 内的文件,可以直接通过 /opt/xxx 访问。如果是访问 node_module 则可以直接 import ,因为 scfNODE_PATH 环境变量默认已包含 /opt/node_modules 路径。

使用 serverless fromwork 的高阶 egg 组件方式部署(不推荐)

目前推荐使用 web 函数,也就是 HTTP 组件 ,现在所有的 serverless web 应用都是基于 component: http 组件的。

  1. 在项目根目录下创建 serverless.yml 文件
npm i serverless -g
# https://github.com/serverless-components/tencent-egg/blob/master/docs/configure.md

# serverless.yml

component: egg # (必选) 组件名称,在该实例中为 egg
name: egg-demo # 必选) 组件实例名称.
# org: orgDemo # (可选) 用于记录组织信息,默认值为您的腾讯云账户 appid,必须为字符串
app: egg-demo # (可选) 用于记录组织信息. 默认与 name 相同,必须为字符串
stage: dev # (可选) 用于区分环境信息,默认值是 dev

inputs:
  region: ap-guangzhou # 云函数所在区域
  functionName: egg-demo # 云函数名称
  # serviceName: egg-demo # api 网关服务名称
  runtime: Nodejs12.16 # 运行环境
  # serviceId: service-np1uloxw # api 网关服务 ID
  # entryFile: sls.js # 自定义 server 的入口文件名,默认为 sls.js,如果不想修改文件名为 sls.js 可以自定义
  # src: ./ # 第一种为 string 时,会打包 src 对应目录下的代码上传到默认 cos 上。
  src:  # 第二种,部署 src 下的文件代码,并打包成 zip 上传到 bucket 上
    src: ./  # 本地需要打包的文件目录
    # bucket: bucket01 # bucket name,当前会默认在 bucket name 后增加 appid 后缀, 本例中为 bucket01-appid
    exclude:   # 被排除的文件或目录
      - .env
      - "node_modules/**"
  # src: # 第三种,在指定存储桶 bucket 中已经存在了 object 代码,直接部署
  #   bucket: bucket01 # bucket name,当前会默认在 bucket name 后增加 appid 后缀, 本例中为 bucket01-appid
  #   object: cos.zip  # bucket key 指定存储桶内的文件
  # layers: 
  #   - name: ${output:${stage}:${app}:egg-demo-layer.name} # 配置对应的 layer
  #     version: ${output:${stage}:${app}:egg-demo-layer.version} # 配置对应的 layer 版本
  functionConf: # 函数配置相关
    timeout: 60 # 超时时间,单位秒
    eip: false # 是否固定出口 IP
    memorySize: 512 # 内存大小,单位 MB
    environment: #  环境变量
      variables: #  环境变量数组
        NODE_ENV: production
    # vpcConfig: # 私有网络配置
      # vpcId: '' # 私有网络的 Id
      # subnetId: '' # 子网 ID
  apigatewayConf: #  api 网关配置
    isDisabled: false # 是否禁用自动创建 API 网关功能
    enableCORS: true #  允许跨域
    # customDomains: # 自定义域名绑定
    #   - domain: abc.com # 待绑定的自定义的域名
    #     certificateId: abcdefg # 待绑定自定义域名的证书唯一 ID
    #     # 如要设置自定义路径映射,请设置为 false
    #     isDefaultMapping: false
    #     # 自定义路径映射的路径。使用自定义映射时,可一次仅映射一个 path 到一个环境,也可映射多个 path 到多个环境。并且一旦使用自定义映射,原本的默认映射规则不再生效,只有自定义映射路径生效。
    #     pathMappingSet:
    #       - path: /
    #         environment: release
    #     protocols: # 绑定自定义域名的协议类型,默认与服务的前端协议一致。
    #       - http # 支持 http 协议
    #       - https # 支持 https 协议
    protocols:
      - http
      - https
    environment: release # 网关环境
    serviceTimeout: 60 # 网关超时
    # usagePlan: #  用户使用计划
    #   usagePlanId: 1111
    #   usagePlanName: slscmp
    #   usagePlanDesc: sls create
    #   maxRequestNum: 1000
    # auth: #  密钥
    #   secretName: secret
    #   secretIds:
    #     - xxx
  1. 将代码推送到云端
sls deploy # sls deploy --debug 可以查看日志
  1. 扫描登录部署会在项目下创建一个 .envserverless 的登录信息

  1. 部署成功,打开地址访问,此时会报错,我们没有把 node_modules 一起上传

浏览器打开提示缺少模块

我们在控制台上点击

打开自动安装依赖后重新部署即可看到 node_modules ,这时再次访问浏览器地址

3.4 sls 部署 nestjs 项目

模板部署 – 部署 Nest.js 示例代码

  1. 登录 Serverless 应用控制台
  2. 单击新建应用,选择 Web 应用>Nest.js 框架,如下图所示:

  1. 单击“下一步”,完成基础配置选择

  • 上传方式,选择示例代码直接部署,单击完成,即可开始应用的部署。
  • 部署完成后,您可在应用详情页面,查看示例应用的基本信息,并通过 API 网关生成的访问路径 URL 进行访问,查看您部署的 Nest.js 项目

自定义模板部署 nest(推荐)

初始化您的 Nest.js 项目

npm i -g @nestjs/cli
nest new nest-app

在根目录下,执行以下命令在本地直接启动服务。

cd nest-app && npm run start

打开浏览器访问 http://localhost:3000,即可在本地完成 Nest.js 示例项目的访问。

部署上云

接下来执行以下步骤,对已初始化的项目进行简单修改,使其可以通过 Web Function 快速部署,此处项目改造通常分为以下两步:

  • 新增 scf_bootstrap 启动文件。
  • 修改监听地址与端口为 0.0.0.0:9000
  1. 修改启动文件 main.ts ,监听端口改为 9000 :

  1. 在项目根目录下新建 scf_bootstrap 启动文件,在该文件添加如下内容(用于启动服务):

您也可以在控制台完成该模块配置。

# scf_bootstrap
#!/bin/bash

SERVERLESS=1 /var/lang/node12/bin/node ./dist/main.js

新建完成后,还需执行以下命令修改文件可执行权限,默认需要 777 或 755 权限才可正常启动。示例如下:

chmod 777 scf_bootstrap

本地配置完成后,执行启动文件,确保您的服务可以本地正常启动,接下来,登录 Serverless 应用控制台,选择 Web 应用>Nest.js 框架,上传方式可以选择本地上传或代码仓库拉取

注意:启动文件以项目内文件为准,如果您的项目里已经包含 scf_bootstrap 文件,将不会覆盖该内容。

使用 http 组件(推荐)

目前推荐使用 web 函数,也就是 HTTP 组件 ,现在所有的 serverless web 应用都是基于 component: http 组件的。

详情查看: https://github.com/serverless-components/tencent-http

# 编写完善配置文件 serverless.yml
# https://github.com/serverless-components/tencent-http/blob/master/docs/configure.md
app: nest-app # 应用名称
component: http # http 组件
name: nest-demo # 实例名称
inputs:
  region: ap-guangzhou # 云函数所在区域
  src: # 部署当前目录下的文件代码,并打包成 zip 上传到 bucket 上
    src: ./ # 当前目录
    exclude: # 被排除的文件或目录
      - .env
      - 'node_modules/**' # 忽略 node_modules,在控制台安装
  # src: # 在指定存储桶 bucket 中已经存在了 object 代码,直接部署
  #   bucket: bucket01 # bucket name,当前会默认在 bucket name 后增加 appid 后缀, 本例中为 bucket01-appid
  #   object: cos.zip  # bucket key 指定存储桶内的文件
  faas: # 函数配置相关
    runtime: Nodejs12.16 # 运行时
    # 支持的框架查看 https://cloud.tencent.com/document/product/1154/59447#framework
    framework: nestjs # #选择框架,此处以 egg 为例 
    name: ${name} # 云函数名称,通过变量形式获取 name 的值
    timeout: 60 # 超时时间,单位秒
    memorySize: 512 # 内存大小,默认 512 MB
    # layers:
    #   - name: layerName #  layer 名称
    #     version: 1 #  版本
    environments: #  配置环境变量,同时也可以直接在 scf 控制台配置 
        - key: NODE_ENV
          value: production
    # vpc: # 私有网络配置
    #   vpcId: 'vpc-xxx' # 私有网络的 Id
    #   subnetId: 'subnet-xxx' # 子网 ID
    # tags:
    #   - key: tagKey
    #     value: tagValue
  apigw: # http 组件会默认帮忙创建一个 API 网关服务
    isDisabled: false # 是否禁用自动创建 API 网关功能
    # id: service-xx # api 网关服务 ID,不填则自动新建网关
    name: serverless # api 网关服务名称
    api: # 创建的 API 相关配置
      cors: true #  允许跨域
      timeout: 30 # API 超时时间
      name: apiName # API 名称
      qualifier: $DEFAULT # API 关联的版本
    protocols:
      - http
      - https
    environment: test
    # tags:
    #   - key: tagKey
    #     value: tagValue
    # customDomains: # 自定义域名绑定
    #   - domain: abc.com # 待绑定的自定义的域名
    #     certId: abcdefg # 待绑定自定义域名的证书唯一 ID
    #     # 如要设置自定义路径映射,(customMap = true isDefaultMapping = false) 必须两者同时出现 其余情况都是默认路径
    #     customMap: true
    #     isDefaultMapping: false
    #     # 自定义路径映射的路径。使用自定义映射时,可一次仅映射一个 path 到一个环境,也可映射多个 path 到多个环境。并且一旦使用自定义映射,原本的默认映射规则不再生效,只有自定义映射路径生效。
    #     pathMap:
    #       - path: /
    #         environment: release
    #     protocols: # 绑定自定义域名的协议类型,默认与服务的前端协议一致。
    #       - http # 支持 http 协议
    #       - https # 支持 https 协议
    # app: #  应用授权配置
    #   id: app-xxx
    #   name: app_demo
    #   description: app description

在项目根目录下新建 scf_bootstrap 启动文件,在该文件添加如下内容(用于启动服务):

#!/bin/bash

SERVERLESS=1 /var/lang/node12/bin/node ./dist/main.js

忽略 node_modules 文件上传

# serverless.yml
exclude: # 被排除的文件或目录
  - .env
  - node_modules/**

执行 sls deploysls deploy --debug 查看部署日志)

查看部署信息

sls info

实时开发并上传

每次改动文件,都实时部署

sls dev

删除部署项目

sls remove

使用 Layer 来减小项目文件大小

随着项目复杂度的增加, deploy 上传会变慢。所以,让我们再优化一下,在项目根目录创建 layer/serverless.yml

# layer/serverless.yml
# https://cloud.tencent.com/document/product/1154/51133
# https://github.com/serverless-components/tencent-layer/blob/master/docs/configure.md

app: nestjs-demo
stage: dev
component: layer # 组件
name: nestjs-demo-layer # 层名称 必须

# 组件参数配置,根据每个组件,实现具体的资源信息配置
inputs:
  name: nestjs-demo-layer
  region: ap-guangzhou
  src:
    src: ../node_modules
    targetDir: /node_modules
  runtimes: # 层支持的运行环境
    - Nodejs12.16
  description: layer description # 否 描述

修改以上项目下的 serverless.yml 加入层配置

回到项目根目录,调整一下根目录的 serverless.yml 下的 layers

# 编写完善配置文件 serverless.yml
# https://github.com/serverless-components/tencent-http/blob/master/docs/configure.md
app: nestjs-demo # 应用名称
stage: dev
component: http # http 组件
name: http-nestjs # 实例名称

inputs:
  src: # 部署当前目录下的文件代码,并打包成 zip 上传到 bucket 上
    dist: ./ # build 后的包
    hook: npm run build # 先构建在上传
    exclude: # 排除的文件
      - .env
      - node_modules/** # deploy 时排除 node_modules [需要注意] 使用 layer 的 node_modules
    src: ./ # 当前目录
  faas: # 函数配置相关
    runtime: Nodejs12.16 # 运行时
    framework: nestjs # #选择框架,此处以 nestjs 为例 
    name: '${name}' # 云函数名称,通过变量形式获取 name 的值
    eip: false
    timeout: 60 # 超时时间,单位秒
    memorySize: 512 # 内存大小,默认 512 MB
    tags: []
    environments: []
    layers: # 配置对应的 layer
      - name: ${output:${stage}:${app}:nestjs-demo-layer.name} # 配置对应的 layer
        version: ${output:${stage}:${app}:nestjs-demo-layer.version} # 配置对应的 layer 版本
  apigw:
    protocols:
      - http
      - https
    timeout: 60
    environment: release
    customDomains: []
  region: ap-guangzhou # 云函数所在区域
  isAutoCiDeploy: false

排除 node_modules

exclude: # 被排除的文件或目录
    - .env
    - node_modules/** # deploy 时排除 node_modules [需要注意] 使用 layer 的 node_modules

配置层

引用格式请参考 变量引用说明 https://github.com/AprilJC/Serverless-Framework-Docs/blob/main/docs/%E5%87%BD%E6%95%B0%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91/%E6%9E%84%E5%BB%BA%E5%BA%94%E7%94%A8.md

layers: # 配置对应的 layer
  - name: ${output:${stage}:${app}:nestjs-demo-layer.name} # 配置对应的 layer
    version: ${output:${stage}:${app}:nestjs-demo-layer.version} # 配置对应的 layer 版本

通过配置层 layer,代码和 node_modules 分离, sls deploy 更快

接着执行命令 sls deploy --target=./layer 部署层,然后再次部署 sls deploy 看看速度应该更快了

每次 node_modules 改变都需要

  • 执行 sls deploy --target=./layer 先部署层, 更新 node_modules
  • 执行 sls deploy 重新部署

layer 的加载与访问

layer 会在函数运行时,将内容解压到 /opt 目录下,如果存在多个 layer ,那么会按时间循序进行解压。如果需要访问 layer 内的文件,可以直接通过 /opt/xxx 访问。如果是访问 node_module 则可以直接 import ,因为 scfNODE_PATH 环境变量默认已包含 /opt/node_modules 路径。

使用 serverless framework 的高阶 nestjs 组件部署(不推荐)

目前推荐使用 web 函数,也就是 HTTP 组件 ,现在所有的 serverless web 应用都是基于 component: http 组件的。

初始化项目

npm i -g @nestjs/cli
nest new nest-app

在根目录下,执行以下命令在本地直接启动服务。

cd nest-app && npm run start

编写项目根目录下 serverless.yml 文件

全部配置详情

https://github.com/serverless-components/tencent-nestjs/blob/master/docs/configure.md

# serverless.yml
component: nestjs # (必选) 组件名称,在该实例中为 nestjs
name: nest-demo # 必选) 组件实例名称.
# org: orgDemo # (可选) 用于记录组织信息,默认值为您的腾讯云账户 appid,必须为字符串
app: app-nest-demo # (可选) 用于记录组织信息. 默认与 name 相同,必须为字符串
stage: dev # (可选) 用于区分环境信息,默认值是 dev

inputs:
  region: ap-guangzhou # 云函数所在区域
  functionName: nest-demo # 云函数名称
  serviceName: nest-demo # api 网关服务名称
  runtime: Nodejs12.16 # 运行环境
  # serviceId: service-jfdasew2112 # api 网关服务 ID 不填默认创建
  # entryFile: sls.js # 自定义 server 的入口文件名,默认为 sls.js,如果不想修改文件名为 sls.js 可以自定义
  # src: ./ # 第一种为 string 时,会打包 src 对应目录下的代码上传到默认 cos 上。
  src:  # 第二种,部署 src 下的文件代码,并打包成 zip 上传到 bucket 上
    src: ./  # 本地需要打包的文件目录
    # bucket: bucket01 # bucket name,当前会默认在 bucket name 后增加 appid 后缀, 本例中为 bucket01-appid
    exclude:   # 被排除的文件或目录
      - .env
      #- "node_modules/**"
  # src: # 第三种,在指定存储桶 bucket 中已经存在了 object 代码,直接部署
  #   bucket: bucket01 # bucket name,当前会默认在 bucket name 后增加 appid 后缀, 本例中为 bucket01-appid
  #   object: cos.zip  # bucket key 指定存储桶内的文件
  # layers: 
    #   - name: ${output:${stage}:${app}:${name}-layer.name} # 配置对应的 layer
    #     version: ${output:${stage}:${app}:${name}-layer.version} # 配置对应的 layer 版本
  functionConf: # 函数配置相关
    timeout: 60 # 超时时间,单位秒
    eip: false # 是否固定出口 IP
    memorySize: 512 # 内存大小,单位 MB
    environment: #  环境变量
      variables: #  环境变量数组
        NODE_ENV: production
    # vpcConfig: # 私有网络配置
      # vpcId: '' # 私有网络的 Id
      # subnetId: '' # 子网 ID
  apigatewayConf: #  api 网关配置
    isDisabled: false # 是否禁用自动创建 API 网关功能
    enableCORS: true #  允许跨域
    # customDomains: # 自定义域名绑定
    #   - domain: abc.com # 待绑定的自定义的域名
    #     certificateId: abcdefg # 待绑定自定义域名的证书唯一 ID
    #     # 如要设置自定义路径映射,请设置为 false
    #     isDefaultMapping: false
    #     # 自定义路径映射的路径。使用自定义映射时,可一次仅映射一个 path 到一个环境,也可映射多个 path 到多个环境。并且一旦使用自定义映射,原本的默认映射规则不再生效,只有自定义映射路径生效。
    #     pathMappingSet:
    #       - path: /
    #         environment: release
    #     protocols: # 绑定自定义域名的协议类型,默认与服务的前端协议一致。
    #       - http # 支持 http 协议
    #       - https # 支持 https 协议
    protocols:
      - http
      - https
    environment: test # 网关环境
    serviceTimeout: 60 # 网关超时
    # usagePlan: #  用户使用计划
    #   usagePlanId: 1111
    #   usagePlanName: slscmp
    #   usagePlanDesc: sls create
    #   maxRequestNum: 1000
    # auth: #  密钥
    #   secretName: secret
    #   secretIds:
    #     - xxx

3.5 sls 部署 koa 项目

控制台部署

  1. 登录 Serverless 应用控制台
  2. 单击新建应用,选择 Web 应用>Koa 框架,如下图所示:

  1. 单击“下一步”,完成基础配置选择。
  2. 上传方式,选择示例代码直接部署,单击完成,即可开始应用的部署。
  3. 部署完成后,您可在应用详情页面,查看示例应用的基本信息,并通过 API 网关生成的访问路径 URL 进行访问,查看您部署的 Koa 项目

自定义模板部署

全局安装 koa-generator 脚手架.

npm install -g koa-generator

创建项目

# 使用 ejs 引擎
koa2 -e koa-demo
cd koa-demo // 进入项目根目录
npm install // 安装项目依赖
npm start

部署上云

接下来执行以下步骤,对已初始化的项目进行简单修改,使其可以通过 Web Function 快速部署,此处项目改造通常分为以下两步:

  • 修改监听地址与端口为 0.0.0.0:9000

具体步骤如下:

在 Koa 示例项目中,修改监听端口到 9000

使用 HTTP 组件部署

编写 serverless.yml

# 文档 https://github.com/serverless-components/tencent-http/blob/master/docs/configure.md
# https://cloud.tencent.com/document/product/1154/59447
# org: '1258157827'
app: koa-demo
stage: dev
component: http # http 组件
name: koa-demo
inputs:
  src:
    src: ./
    exclude: # 排除文件,在控制台 WEBIDE 开启自动安装依赖
      - .env
      - node_modules
  region: ap-guangzhou
  isAutoCiDeploy: false
  faas:
    runtime: Nodejs12.16
    eip: false
    timeout: 30
    memorySize: 512
    tags: []
    framework: koa # koa 框架
    environments: []
    # layers:
    #   - name: '${output:${stage}:${app}:koa-demo-layer.name}'
    #     version: '${output:${stage}:${app}:koa-demo-layer.version}'
  apigw:
    timeout: 60
    protocols:
      - http
      - https
    environment: release
    customDomains: []

项目根目录新增 scf_bootstrap 启动文件

touch scf_bootstrap

# 还需执行以下命令修改文件可执行权限,默认需要 777 或 755 权限才可正常启动
chmod 777 scf_bootstrap

scf_bootstrap

#!/bin/bash
/var/lang/node12/bin/node bin/www # 修改入口为 bin/www,并且修改 bin/www 下端口为 9000

部署

sls deploy

查看部署信息

sls info

移除

sls remove

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文