poetry

V1

2022/07/29阅读:10主题:姹紫

serverless从入门到实践总结篇

  • 原文:https://blog.poetries.top/2022/06/18/serverless-deploy-summary
  • 前端进阶之旅:https://interview2.poetries.top
  • 博客:https://blog.poetries.top
  • 公众号/小程序:「前端进阶之旅」 每天分享技术干货,学前端不迷路
  • 作者:程序员poetry

一、serverless架构介绍及安装serverless

  • Serverless又名无服务器,所谓无服务器并非是说不需要依赖和依靠服务器等资源,而是开发者再也不用过多考虑服务器的问题,可以更专注在产品代码上。
  • Serverless是一种软件系统架构的思想和方法,它不是软件框架、类库或者工具。它与传统架构的不同之处在于,完全由第三方管理,由事件触发,存在于无状态(Stateless)、 暂存(可能只存在于一次调用的过程中)计算容器内。构建无服务器应用程序意味着开发者可以专注在产品代码上,而无须管理和操作云端或本地的服务器或运行时(运行时通俗的讲 就是运行环境,比如 nodejs 环境,java 环境,php 环境)。Serverless 真正做到了部署应用 无需涉及基础设施的建设,自动构建、部署和启动服务。

通俗的讲:Serverless 是构建和运行软件时不需要关心服务器的一种架构思想

虚拟主机已经是快被淘汰掉的上一代产物了。云计算涌现出很多改变传统 IT 架构和运维方 式的新技术,比如虚拟机、容器、微服务,无论这些技术应用在哪些场景,降低成本、提升 效率是云服务永恒的主题。Serverless 的出现真正的解决了降低成本、提升效率的问题。它真正做到了弹性伸缩高并发按需收费备份容灾、日志监控等。

1.1 传统的开发模式与serverless开发模式对比

传统的开发模式

新型的serverless开发模式

Serverless 正在改变未来软件开发的模式和流程

1.2 Serverless 和 ServerFul 架构的区别

传统的 ServerFul 架构模式

ServerFul 架构就是 n 台 Server 通过 网络通信 的 方式 协作在一起,也可以说 ServerFul 架构是基于 Server 和 网络通信(分布式计算) 的 软件实现架构 , Server 可 以是 虚拟机 物理机 ,以及基于硬件实现的云的云服务器

Serverless 架构模式

Serverless 的核心特点就是实现自动弹性伸缩和按量付费

1.3 使用serverless的优势

  • 资源分配: 在 Serverless 架构中,你不用关心应用运行的资源(比如服务配置、磁盘大小)只提供一份代码就行。
  • 计费方式: 在 Serverless 架构中,计费方式按实际使用量计费(比如函数调用次数、运 行时长),不按传统的执行代码所需的资源计费(比如固定 CPU)。计费粒度也精确到了毫 秒级,而不是传统的小时级别。个别云厂商推出了每个月的免费额度,比如腾讯云提供了每 个月 40 万 GBs 的资源使用额度和 100 万次调用次数的免费额度。中小企业的网站访问量不 是特别大的话完全可以免费使用。
  • 弹性伸缩: Serverless 架构的弹性伸缩更自动化、更精确,可以快速根据业务并发扩容更 多的实例,甚至允许缩容到零实例状态来实现零费用,对用户来说是完全无感知的。而传统 架构对服务器(虚拟机)进行扩容,虚拟机的启动速度也比较慢,需要几分钟甚至更久。

1.4 Serverless 组成

  • 广义的 Serverless 更多是指一种技术理念:Serverless 是构建和运行软件时不需要关心服务 器的一种架构思想。刚开始学 Serverless 你可以把它理解为虚拟主机的升级版本
  • 狭义的 Serverless 是指现阶段主流的技术实现:狭义的 Serverless 是 FaaSBaaS 组成

1.5 Serverless 开发流程

1.6 为什么要学 Serverless

先看看招聘信息

看看最近 2 年 Github 的 start 数量和周下载量

目前已经使用了 serverless 的大公司

1.7 Serverless 的能力

计算能力

  • 资源按需分配,无需申请资原
  • Mwm:租户级别强镜离 Docker:进程级别隔离
  • Mwm+Docker 轻量级资源毫秒级启动
  • 实时扩容,阶梯缩容
  • 按需收费

系统运维能力

  • 性能保障:整个链路耗时毫秒级内,并支持 VPC 内网访问
  • 安全保障
    • 资源对用户不可见,安全由腾讯云提供专业的保障
    • 提供进程级和用户级安全隔离
    • 访问控制管理
  • 自动性护缩容
    • 根据 CPU 内容网络 IO 自动扩容底层资源
    • 根据请求数自动扩缩容函数实例,业务高峰期扩容,满足业务高并发需求,业务低 峰期缩容,释放资源,降低成本
  • 自愈能力:每一次请求都是一个健康的实例

Serverless 中云函数被第一次调用会执行冷启动,Serverless 中云函数被多次连续调用会 执行热启动

  • 冷启动 是指你在服务器中新开辟一块空间供一个函数实例运行,这个过程有点像你把这 个函数放到虚拟机里去运行,每次运行前都要先启动虚拟机加载这个函数,以前冷启动非常 耗时,但是目前云厂商已经能做到毫秒级别的冷启动,这个过程我们也不需要关心,但是需 要注意的是使用 Seesion 的时候可能会导致 Session 丢失,所以我们的 Seesion 建议保存到数 据库。
  • 热启动 则是说如果一个云函数被持续触发,那我就先不释放这个云函数实例,下次请求 仍然由之前已经创建了的云函数实例来运行,就好比我们打开虚拟机运行完这个函数之后没 有关闭虚拟机,而是让它待机,等待下一次被重新触发调用运行,这样做的好处就是省去了 给虚拟机「开机」的一个耗时环节,缺点是要一直维持这个虚拟机的激活状态,系统开销会 大一些。

业务运维能力

  • 工具建设:vscode 插件、WebIDE、Command Line、云 api、Sdk
  • 版本管理、操作管理等
  • 故障排查
  • 监控报警
  • 容灾处理

1.8 serverless厂家

1.9 云函数和serverless的区别

通过前面的介绍,我们认识到了云函数和serverless,但是可能会有一个很迷惑云函数和serverless到底有什么区别,他们之间有什么联系,为什么我在创建云函数的时候选择模板方式创建最后创建的是serverless,而不是云函数呢。下面我们将解答云函数和serverless的区别

  • Serverless FrameworkServerless公司推出的一个开源的 Serverless 应用开发框架
  • Serverless Framework是由 Serverless Framework PluginServerless Framework Components 组成
  • Serverless Framework Plugin 实际上是一个函数的管理工具,使用这个工具,可以很轻松的 部署函数、删除函数、触发函数、查看函数信息、查看函数日志、回滚函数、查看函数 数据等。简单的概括就是serverless其实就云函数的集合体,使用serverless后我们创建的云函数不需要手动去创建触发器等操作

官方地址

1.20 创建serverless的方式

  • 在腾讯serverless控制面板上创建,然后在vscode中使用插件的方式下载到本地(**注意: ** 编辑器上要选择和创建serverless地区相同,才能看到项目,否则是看不到项目代码的)
  • 使用客户端serverless cli命令方式创建,个人也更推荐使用这种方式创建,修改代码,然后部署到后台腾讯云服务上

二、serverless 脚手架安装、WebIDE中创建、vscode中配置

2.1 脚手架安装-三分钟部署一个项目

npm i serverless -g

serverless -v

查看支持的框架部署

sls registry

# 或者输入sls
sls
# 例如初始化egg项目

serverless init eggjs-starter(可以替换成sls registry已有的模板) --name egg-example

部署

sls deploy

2.2 在vscode中配置插件来开发serverless

通过该 VS Code 插件,您可以

  • 拉取云端的云函数列表,并触发云函数
  • 在本地快速创建云函数项目
  • 使用模拟的 COS、CMQ、CKafka、API 网关等触发器事件来触发函数运行
  • 上传函数代码到云端,更新函数配置
  • 在云端运行、调试函数代码

界面上创建应用

  • vscode上安装插件
  • vscode安装后插件登录并且拉取应用

密钥地址 https://console.cloud.tencent.com/cam/capi 填入appID、secretID、secretKey即可拉取云函数到本地

  • 切换地域查看函数
  • 点击云函数,可以查看函数基本配置信息
  • 下载函数代码到本地调试,点击下载图标选择要保存的路径
  • 本地修改完代码后,上传函数代码到云端

  • 本地调试云函数

2.3 WebIDE创建云函数实践

创建一个云函数

给云函数创建触发器来访问

创建了触发器后,就可以通过触发器里面的访问路径来访问云函数

我们可以在控制台修改代码,然后重新部署云函数,或者开启自动安装依赖等

三、Serverless Framework部署项目实战

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 官网:https://www.serverless.com/
  • Serverless Framework 中文网站:https://www.serverless.com/cn
  • Github 地址:https://github.com/serverless/serverless

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#%E5%8F%98%E9%87%8F%E5%BC%95%E7%94%A8%E8%AF%B4%E6%98%8E
    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#%E5%8F%98%E9%87%8F%E5%BC%95%E7%94%A8%E8%AF%B4%E6%98%8E

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#%E5%8F%98%E9%87%8F%E5%BC%95%E7%94%A8%E8%AF%B4%E6%98%8E

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

四、部署静态网站

  • 全部配置 https://github.com/serverless-components/tencent-website/blob/master/docs/configure.md
  • 部署文档 https://cloud.tencent.com/document/product/1154/39276

部署的静态资源会存储到COS中

4.1 sls部署vue项目

初始化项目

vue init webpack vue-demo

编写serverless.yml

# https://github.com/serverless-components/tencent-website/blob/master/docs/configure.md
# https://cloud.tencent.com/document/product/1154/39276
component: website # (必填) 引用 component 的名称,当前用到的是 tencent-website 组件
name: vue-demo # (必填) 该 website 组件创建的实例名称

app: vue-demo # (可选) 该 website 应用名称
stage: dev # (可选) 用于区分环境信息,默认值是 dev

inputs:
  src:
    # 部署项目的目录路径
    src: ./ 
    dist: ./dist # build 完成后输出目录,如果配置 hook, 此参数必填
    index: index.html # 网站主页入口文件
    error: 404.html # 网站错误入口文件
    hook: npm run build #  构建命令,在代码上传之前执行
    # websitePath: ./
  region: ap-guangzhou
  bucketName: vue-test-demo # OSS存储桶名称
  protocol: https
  replace: false # 是否覆盖式部署
  ignoreHtmlExt: false # 是否是否忽略 html 扩展名,默认 false
  disableErrorStatus: false # 是否禁用错误码,默认 false
  autoSetupAcl: true # 自动配置 bucket 访问权限为 ”公有读私有写“
  autoSetupPolicy: false # 自动配置 bucket 的 Policy 权限为 ”所有用户资源可读“
  # env: # 配置前端环境变量
  #   API_URL: https://api.com
  # hosts:
  #   - host: test.com # 自定义域名
  #     async: false # 是否同步等待 CDN 配置。配置为 false 时,参数 autoRefresh 自动刷新才会生效,如果关联多域名时,为防止超时建议配置为 true。
  #     autoRefresh: true #开启自动 CDN 刷新,用于快速更新和同步加速域名中展示的站点内容

执行部署

sls deploy

如果希望查看更多部署过程的信息,可以通过sls deploy --debug 命令查看部署过程中的实时日志信息

开发调试

部署了静态网站应用后,可以通过开发调试能力对该项目进行二次开发,从而开发一个生产应用。在本地修改和更新代码后,不需要每次都运行 serverless deploy 命令来反复部署。您可以直接通过 serverless dev 命令对本地代码的改动进行检测和自动上传。

  • 可以通过在 serverless.yml 文件所在的目录下运行 serverless dev 命令开启开发调试能力。
  • serverless dev 同时支持实时输出云端日志,每次部署完毕后,对项目进行访问,即可在命令行中实时输出调用日志,便于查看业务情况和排障。

查看状态

serverless.yml文件所在的目录下,通过如下命令查看部署状态:

serverless info

移除

serverless.yml文件所在的目录下,通过以下命令移除部署的静态网站 Website 服务。移除后该组件会对应删除云上部署时所创建的所有相关资源。

$ serverless remove

和部署类似,支持通过 sls remove --debug 命令查看移除过程中的实时日志信息

4.2 sls部署react项目

初始化项目

npm i create-umi -g
create-umi react-demo

编写serverless.yml

# https://github.com/serverless-components/tencent-website/blob/master/docs/configure.md
# https://cloud.tencent.com/document/product/1154/39276
component: website # (必填) 引用 component 的名称,当前用到的是 tencent-website 组件
name: react-demo # (必填) 该 website 组件创建的实例名称

app: react-demo # (可选) 该 website 应用名称
stage: dev # (可选) 用于区分环境信息,默认值是 dev

inputs:
  src:
    # 执行目录路径
    src: ./ 
    dist: ./dist # 部署目录路劲
    index: index.html # 网站主页入口文件
    error: 404.html # 网站错误入口文件
    hook: npm run build #  构建命令,在代码上传之前执行
  region: ap-guangzhou
  bucketName: react-test-demo # OSS存储桶名称
  protocol: https
  replace: false # 是否覆盖式部署
  ignoreHtmlExt: false # 是否是否忽略 html 扩展名,默认 false
  disableErrorStatus: false # 是否禁用错误码,默认 false
  autoSetupAcl: true # 自动配置 bucket 访问权限为 ”公有读私有写“
  autoSetupPolicy: false # 自动配置 bucket 的 Policy 权限为 ”所有用户资源可读“
  # env: # 配置前端环境变量
  #   API_URL: https://api.com
  # hosts:
  #   - host: test.com # 自定义域名
  #     async: false # 是否同步等待 CDN 配置。配置为 false 时,参数 autoRefresh 自动刷新才会生效,如果关联多域名时,为防止超时建议配置为 true。
  #     autoRefresh: true #开启自动 CDN 刷新,用于快速更新和同步加速域名中展示的站点内容

实时监控项目部署

sls dev

4.3 sls部署vuepress项目

编写serverless.yml配置

# https://github.com/serverless-components/tencent-website/blob/master/docs/configure.md
# https://cloud.tencent.com/document/product/1154/39276
component: website # (必填) 引用 component 的名称,当前用到的是 tencent-website 组件
name: vuepress-demo # (必填) 该 website 组件创建的实例名称

app: vuepress-demo # (可选) 该 website 应用名称
stage: dev # (可选) 用于区分环境信息,默认值是 dev

inputs:
  src:
    src: .vuepress # (必填) .vuepress源文件夹路径
    dist: .vuepress/dist # 部署目录路径
    index: index.html # 网站主页入口文件
    error: 404.html # 网站错误入口文件
    hook: npm run build #  构建命令,在代码上传之前执行
  region: ap-guangzhou
  bucketName: vuepress-test-demo # OSS存储桶名称
  protocol: https
  replace: false # 是否覆盖式部署
  ignoreHtmlExt: false # 是否是否忽略 html 扩展名,默认 false
  disableErrorStatus: false # 是否禁用错误码,默认 false
  autoSetupAcl: true # 自动配置 bucket 访问权限为 ”公有读私有写“
  autoSetupPolicy: false # 自动配置 bucket 的 Policy 权限为 ”所有用户资源可读“
  # hosts:
  #   - host: test.com # 自定义域名
  #     async: false # 是否同步等待 CDN 配置。配置为 false 时,参数 autoRefresh 自动刷新才会生效,如果关联多域名时,为防止超时建议配置为 true。
  #     autoRefresh: true #开启自动 CDN 刷新,用于快速更新和同步加速域名中展示的站点内容

执行部署

sls deploy

移除

sls remove

五、综合实战

5.1 Serverless中使用Node操作Mysql、Mongodb数据库、以及配置VPC私有网络

云函数接入数据库

参考:https://cloud.tencent.com/document/product/583/51935

注意:配置私有网络的服务器需要在同一个地区

Nodejs Serverless 中操作 Mysql

  • 准备工作:首先需要购买云数据库、或者自己在服务器上面搭建一个数据库
  • 云函数操作 Mysql

购买云数据库mysql

新建mysql云函数

  • 选择和mysql同一个地域,程序之间通过VPC网络连接
  • 选择私有网络,和mysql所在网络一致

如果没有需要新建私有网络,需要和msyql实例同一个地区,选择了新建的私有网络,mysql实例那边网络需要修改一致

  • 登录mysql数据库增加测试数据

新建test数据库

创建user表

  • 修改云函数代码,保存部署即可
/**************************************************
Node8.9-Mysql
Reference: mysql api---https://www.npmjs.com/package/mysql
Reference: How to access database---https://cloud.tencent.com/document/product/236/3130
Reference: How to connect api gateway with scf---https://cloud.tencent.com/document/product/628/11983
***************************************************/


function wrapPromise(connection, sql{
  return new Promise((res, rej) => {
    connection.query(sql, function(error, results, fields{
      if (error) {
        rej(error)
      }
      res(results)
    })
  })
}


exports.main_handler = async (event, context, callback) => {
  const mysql = require('mysql');
  const connection = mysql.createConnection({
    host'167.16.0.17'// The ip address of cloud database instance, 云数据库实例ip地址
    user'root'// The name of cloud database, for example, root, 云数据库用户名,如root
    password'xx'// Password of cloud database, 云数据库密码
    database'test'// Name of the cloud database, 数据库名称
    port"3306"
  });

  connection.connect();

  const querySql = `SELECT * from user`

  let queryResult = await wrapPromise(connection, querySql)
  
  connection.end();

  return queryResult
}

重新部署

  • 创建API网关触发器,在浏览器中访问

浏览器中访问查看效果

Nodejs Serverless 中操作 Mongodb

  • 准备工作:首先需要购买云数据库、或者自己在服务器上面搭建一个数据库
  • 云函数操作 Mongodb

购买MongoDB数据库

创建云函数

  • 选择地区
  • 选择私有网络,和mongodb所在网络一致
  • 修改云函数代码
const {promisify} = require('util')
const mongodb = require('mongodb')

var mongoClient = mongodb.MongoClient,
    assert = require('assert');

const connect = promisify(mongodb.connect)

// URL combination
// var url = 'mongodb://mason_mongodb:mason12345@10.10.11.19:27017/admin';

var url="mongodb://mongouser:password@10.0.0.13:27017,10.0.0.8:27017,10.0.0.11:27017/admin?authSource=admin&replicaSet=cmgo-e23piswf_0"

exports.main_handler = async (event, context, callback) => {
    console.log('start main handler')
    const MongoClient = require("mongodb").MongoClient;
    const mc = await MongoClient.connect(url,{useNewUrlParsertrue})
    const db = mc.db('testdb'
    const collection = db.collection('demoCol')
    await collection.insertOne({a:1,something:'你好 serverless'})
    const as = await collection.find().toArray()
    console.log(as)

    mc.close()

    return as
}

创建触发器

5.2 Serverless BaaS 对象云存储Cos介绍、Node操作Cos、实现图片上传到Cos中

对象云存储 Cos 介绍

狭义的 Serverless 是指现阶段主流的技术实现:狭义的 Serverless 是 FaaSBaaS 组成

对象存储(Cloud Object Storage,COS)是一种存储海量文件的分布式存储服务,具有高扩 展性、低成本、可靠安全等优点。通过控制台、API、SDK 和工具等多样化方式,用户可简 单、快速地接入 COS,进行多格式文件的上传、下载和管理,实现海量数据存储和管理。

Nodejs 操作 Cos

参考官方文档:https://cloud.tencent.com/document/product/436/8629

cnpm i cos-nodejs-sdk-v5 --save
const COS = require('cos-nodejs-sdk-v5');
const fs=require("fs");

//配置cos的sdk  https://console.cloud.tencent.com/cam/capi
var cos = new COS({
    SecretId'xx',
    SecretKey'xx'
});

//上传本地图片到对象云存储里面
cos.putObject({
    Bucket'express-demo-1251179943'/* 必须存储桶名称 */
    Region'ap-guangzhou',    /* 必须 区域*/
    Key'a.png',              /* 必须   目录/文件的名称  */
    StorageClass'STANDARD',
    Body: fs.createReadStream('./a.png'), // 上传文件对象
    onProgressfunction(progressData{
      console.log(JSON.stringify(progressData));
    }
}, function(err, data{
    console.log(err || data);
});

Express 在 Serverless 中实现图片上传到 Cos 中

安装模块 multer https://github.com/expressjs/multer

npm install --save multer

配置 form 表单

<!-- views/index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Serverless Component - Express.js</title>
    <link rel="stylesheet" href="/css/basic.css">
  </head>
  <body>
    <form action="/doUpload" method="post" enctype="multipart/form-data">
      用户名:<input type="text" name="username" />
      <br>
      <br>
      头 像 : <input type="file" name="face" />
      <br>
      <br>
      <input type="submit" value="提交">
    </form>
  </body>
</html>

配置内存存储引擎 (MemoryStorage),内存存储引擎将文件存储在内存中的 Buffer 对象,它没有任何选项

var storage = multer.memoryStorage()
var upload = multer({ storage: storage })

接收文件上传文件到云存储

// app.js
const express = require('express');
const path = require('path');
const ejs = require("ejs");
var bodyParser = require('body-parser')
var multer = require('multer');
var tools = require('./services/tools.js');

const app = express();

//配置上传
var storage = multer.memoryStorage();
var upload = multer({ storage: storage });

// 配置中间件
app.use(bodyParser.urlencoded({ extendedfalse }));
app.use(bodyParser.json())

//配置模板引擎
app.engine("html", ejs.__express)
app.set("view engine""html")

//会对指定类型进行 Base64 编码
app.binaryTypes = ['*/*'];

//静态web服务
app.use(express.static("public"));
// Routes
app.get(`/`, (req, res) => {
  res.render("index", {
    title"你好serverless"
  })
});

//注意:https://github.com/serverless-components/tencent-koa/blob/master/docs/upload.md
app.post(`/doUpload`, upload.single("face"), async (req, res) => {
  console.log(req.body);
  console.log(req.file);

  //上传本地图片到对象云存储里面   注意异步
  let result = await tools.uploadCos(req.file.originalname, req.file.buffer)

  res.send({
    body: req.body,
    result: result
  });
});


// Error handler
app.use(function (err, req, res, next{
  console.error(err);
  res.status(500).send('Internal Serverless Error');
});

module.exports = app;
// services/tools.js
const COS = require('cos-nodejs-sdk-v5');

module.exports={
  uploadCos(filename,source){
    let cos = new COS({
      SecretId'xx',
      SecretKey'xx'
    });
    return new Promise((reslove, reject) => {
      cos.putObject({
        Bucket'test-xx'/* 必须 */
        Region'ap-beijing',    /* 必须 */
        Key'test/' + filename,              /* 必须 test为目录名称 */
        StorageClass'STANDARD',
        Body: source, // 上传文件对象
        onProgressfunction (progressData{
          console.log(JSON.stringify(progressData));
        }
      }, function (err, data{
          if(err){
              reject(err);
          }else{
              reslove(data);
          }
        
      });
    })
  }
}

上传文件需要注意

https://github.com/serverless-components/tencent-koa/blob/master/docs/upload.md

修改serverless.yml

app: appDemo
stage: dev
component: koa
name: koaDemo

inputs:
  # 省略...
  apigatewayConf:
    isBase64Encoded: true # 需要加上,否则上传图片到cos预览有问题
    # 省略...
  # 省略...

完整serverless.yml

app: expressdemo
component: express
name: expressDemo
inputs:
  runtime: Nodejs10.15
  region: ap-guangzhou
  src:
    src: ./
    exclude:
      - .env
      - .git
      - node_modules
  apigatewayConf:
    enableCORS: false
    isBase64Encoded: true # 需要加上,否则上传图片到cos预览有问题
    protocols:
      - http
      - https
    environment: release

部署,然后在webIDE开启自动安装依赖

sls deploy

5.3 Serverless、Cos中配置域名访问以及Serverless中配置https访问

Serverless 中配置域名访问

找到云函数对应的 api 网关

编辑 api 网关 点击域名管理

新建域名

解析域名

Serverless 中配置 https 访问

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版。

HTTPS 是在 HTTP 的基础上添加了安全层,从原来的明文传输变成密文传输,当然加密与解 密是需要一些时间代价与开销的,不完全统计有 10 倍的差异。

在当下的网络环境下可以忽 略不计,已经成为一种必然趋势。 目前微信小程序请求 Api 必须用 https、Ios 请求 api 接口必须用 https

https 证书类型

  • 域名型 https 证书(DVSSL):信任等级一般,只需验证网站的真实性便可颁发证书保护网站
  • 企业型 https 证书(OVSSL):信任等级强,须要验证企业的身份,审核严格,安全性更高
  • 增强型 https 证书(EVSSL):信任等级最高,一般用于银行证券等金融机构,审核严格,安全性最高, 同时可以激活绿色网址栏

创建证书

选择证书

Cos 中配置域名

配置域名

域名解析

六、QA

scf_bootstrap启动文件与sls.js启动文件区别

  • scf_bootstrap 文件是针对 web 函数的,
  • sls.js 入口文件是针对事件函数,主要是 serverless 封装了一些开源框架,改造的入口文件。

关于serverless.yml写法问题,是更推荐HTTP组件方式吗

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

关于配额问题如何处理

云函数 scf 针对每个用户帐号,均有一定的配额限制:

其中需要重点关注的就是单个函数代码体积 500mb 的上限。在实际操作中,云函数虽然提供了 500mb。但也存在着一个 deploy 解压上限。

关于绕过配额问题:

  • 如果超的不多,那么使用 npm install --production 就能解决问题
  • 如果超的太多,那就通过挂载 cfs 文件系统来进行规避(参考文章

七、官方文档

原文地址 https://blog.poetries.top/2022/06/18/serverless-deploy-summary

分类:

前端

标签:

React.js

作者介绍

poetry
V1