云开发 Serverless 从入门到实战

Serverless

指构建和运行不需要服务器管理的应用程序的概念。
Serverless 是 FaaS 和 BaaS 的结合。Serverless = FaaS + BaaS。

FaaS(Function as a Service) 就是一些运行函数的平台,比如阿里云的函数计算、AWS 的 Lambda 等。
BaaS(Backend as a Service)则是一些后端云服务,比如云数据库、对象存储、消息队列等。利用 BaaS,可以极大简化我们的应用开发难度。

Serverless 的主要特点有:

  • 事件驱动
  • 函数在 FaaS 平台中,需要通过一系列的事件来驱动函数执行。
  • 无状态
  • 因为每次函数执行,可能使用的都是不同的容器,无法进行内存或数据共享。如果要共享数据,则只能通过第三方服务,比如 Redis 等。
  • 无运维
  • 使用 Serverless 我们不需要关心服务器,不需要关心运维。这也是 Serverless 思想的核心。
  • 低成本
  • 使用 Serverless 成本很低,因为我们只需要为每次函数的运行付费。函数不运行,则不花钱,也不会浪费服务器资源

前端工程师基于 Serverless 去写后端,最好也需要具备一定的后端知识。涉及复杂的后端系统或者 Serverless 不适用的场景,还是需要后端开发,后端变得更靠后了。

Serverless 开发最佳实践

将业务逻辑和函数依赖的 FaaS(如函数计算) 和 BaaS (如云数据库)分离。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Users {
constructor(db, mailer) {
this.db = db;
this.mailer = mailer;
}
save(email, callback) {
const user = {
email: email,
created_at: Date.now()
}
this.db.saveUser(user, function (err) {
if (err) {
callback(err);
} else {
this.mailer.sendWelcomeEmail(email);
callback();
}
});
}
}
module.exports = Users;

const db = require('db').connect();
const mailer = require('mailer');
const Users = require('users');
let users = new Users(db, mailer);
module.exports.saveUser = (event, context, callback) => {
users.save(event.email, callback);
};

将业务逻辑全都放在了 Users 这个类里面,Users 不依赖任何外部服务。

函数的性能

当驱动函数执行的事件到来的时候,首先需要下载代码,然后启动一个容器,在容器里面再启动一个运行环境,最后才是执行代码。前几步统称为冷启动(Cold Start)。传统的应用没有冷启动的过程。

当第一次请求(驱动函数执行的事件)来临,成功启动运行环境并执行函数之后,运行环境会保留一段时间,以便用于下一次函数执行。这样就能减少冷启动的次数,从而缩短函数运行时间。当请求达到一个运行环境的限制时,FaaS 平台会自动扩展下一个运行环境。

执行上下文重用

1
2
3
4
5
6
const mysql = require('mysql');
// 初始化数据库连接 const connection = mysql.createConnection({ /* ... */ });
connection.connect();
module.exports.saveUser = (event, context, callback) => {
connection.query('...');
};

这样就只有第一次运行环境启动的时候,才会初始化数据库连接。后续请求来临、执行函数的时候,就可以直接利用执行上下文中的 connection,从而提高后续高函数的性能。
大部分情况下,通过牺牲一个请求的性能,换取大部分请求的性能,是完全可以够接受的。

给函数预热

通过主动调用函数的方式,隔一段时间就冷启动一个运行环境,这样就能使得其他正常的请求都是热启动,从而避免冷启动时间对函数性能的影响。

需要注意:

  • 不要过于频繁调用函数,至少频率要大于 5 分钟
  • 直接调用函数,而不是通过网关等间接调用
  • 创建专门处理这种预热调用的函数,而不是正常业务函数

如果你的业务允许“牺牲第一个请求的性能换取大部分性能”,那也完全不必使用该方案,

CloudBase

腾讯云CloudLite认证-云开发 CloudBase

初识云开发 CloudBase

  • 传统开发模式的问题
  • 云开发 CloudBase 产品介绍

云函数

运行在云端的代码,无需管理服务器

云数据库

即可在前端操作,也能在云函数中读写的 JSON 数据库

云存储

前端可直接上传/下载云端文件,云开发控制台可视化管理

静态托管

一键将静态网站资源部署在云端,提供 CDN 进行加速

云应用

无服务器容器托管平台,用户可面向代码/镜像等多种方式使用

扩展能力

  • 图像处理
    裁剪、压缩、盲水印、标签、安全审核。
  • 数据库
    支持 mysql、redis等数据库的快速接入。
  • CMS 内容管理系统
    免开发的内容管理系统,方便运营。

Web 云开发快速开始

开通环境

注册腾讯云账号
开通云开发环境

  • 控制台
  • 云产品
  • 云开发 CloudBase

获取 SDK

  • SDK 版本
  • SDK 链接

配置开发环境

  • Node.js > 8.6.0
  • CloudBase CLI 是开源命令行界面交互工具,用于帮助用户快速、方便的部署项目,
  • npm i -g @cloudbase/cli 安装云开发
  • 在 VSCode 中搜索 Tencent CloudBase Toolkit 即可安装

创建初始化项目

  • vue create cloudbase 创建 Vue 项目
  • 配置云开发 SDK
    npm i –save tcb-js-sdk@latest
1
2
3
4
5
6
7
8
9
10
11
import Vue from 'vue'
import App from './App.vue'
const tcb = require('tcb-js-sdk')
const app = tcb.init({
env:'env-rahqdieb'
})
Vue.config.productionTip = false

new Vue({
render:h => h(App),
}).$mount('#app')

添加安全域名

  • 打开云开发控制台,左侧的环境-安全配置-Web 安全域名

开启匿名登录

云开发支持 微信公众号登录、微信开发平台登录、匿名登录、邮箱登录、短信验证码登录自定义登录
自定义登录可以用于实现各种自定义的登录逻辑、如LDAP、HTTP Basic等。

  • 云开发的资源要用户登录后才可以调用,匿名登录也是一种登录状态
  • 访问云开发控制台
  • 找到环境-登录授权
  • 开启匿名登录选项
    开启匿名登录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue'
import App from './App.vue'
const tcb = require('tcb-js-sdk')
const app = tcb.init({
env:'env-rahqdieb'
})
app.auth({
persistence:"session"
}).anonymousAuthProvider().signIn().then(()=>{
// 登录成功
}).catch(err=>{
// 登录失败
})
Vue.config.productionTip = false

new Vue({
render:h => h(App),
}).$mount('#app')

调用云开发资源

  • 云开发支持在 Web 页面中直接调用云开发数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import Vue from 'vue'
import App from './App.vue'
const tcb = require('tcb-js-sdk')
const app = tcb.init({
env:'env-rahqdieb'
})
app.auth({
persistence:"session"
}).anonymousAuthProvider().signIn().then((res)=>{
console.log('登录成功',res)
// 登录成功
const db = app.database();
const collection = db.collection('user');
collection.get().then(result => {
console.log(result.data); // 这里可以获取到数据
})
}).catch(error => {
// 登录失败
console.log('登录失败',error)
})
Vue.config.productionTip = false

new Vue({
render:h => h(App),
}).$mount('#app')

调用云开发函数
云开发支持在 Web 页面中直接调用云开发函数

1
2
3
4
5
6
app.callFunction({
name: 'test',
data: { a : 1}
}).then((res)=>{
const result = res.result; // 云函数执行结果
})

新建目录 cloud
打开 Tencent CloudBase Toolkit 插件,点击初始化云开发项目,选择环境,选择类型
npm init,上传部署云函数,在 vue 项目中调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import Vue from 'vue'
import App from './App.vue'
const tcb = require('tcb-js-sdk')
const app = tcb.init({
env:'env-rahqdieb'
})
app.auth({
persistence:"session"
}).anonymousAuthProvider().signIn().then((res)=>{
console.log('登录成功',res)
// 登录成功
const db = app.database();
const collection = db.collection('user');
collection.get().then(result => {
console.log("数据库返回值",result.data);
}).catch(error => {
console.log('查询出错' error)
})
app.callFunction({
name: 'node-app',
data: {
text: 'hello world',
invoker: 'browser'
}
}).then(item => {
console.log(item)
}).catch(error =>{
console.log(error);
})
}).catch(error => {
// 登录失败
console.log('登录失败',error)
})
Vue.config.productionTip = false

new Vue({
render:h => h(App),
}).$mount('#app')

部署静态页面

配置云开发 CLI

  • 使用云开发 CLI 可以快速完成项目的上传和部署
  • 执行 npm i -g @cloudbase/cli 安装云开发 CLI
  • 使用 cloudbase login 完成用户登录
  • 进入项目根目录,执行 cloudbase hosting:deploy -e envId 部署静态文件

npm run build 构建静态页面
cd dist
cloudbase login
cloudbase hosting:deploy -e env-rahqdied
开启静态网站服务

  • 打开云开发控制台
  • 静态网站托管 基础配置 默认域名

30分钟创建并上线小程序项目

不勾选云开发,新建文件,在 project.config.json 中指定云开发根目录

1
2
3
4
{
"description": "项目配置文件",
"cloudfunctionRoot": "cloudfunctions/",
}

指定云开发环境

1
2
3
4
5
6
7
8
9
10
11
12
App({
onLaunch: function () {
// app.js
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else {
wx.cloud.init({
env: 'cloud-demo-51566c',
traceUser: true,
})
}
}

登录功能(云函数的创建和调用)

1
2
3
4
<open-data type="userAvatarUrl"></open-data>
<open-data type="userNickName"></open-data>
<button wx:if="{{canIUse}}" open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="onGotUserInfo" >登录</button>
<view wx:else>请升级微信版本</view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
data: {
canIUse: wx.canIUse('button.open-type.getUserInfo'),
userInfo:{}
},
onGotUserInfo(e){
console.log(e.detail.userInfo)
},
onLoad: function (options) {
// 查看是否授权
wx.getSetting({
success (res){
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称
wx.getUserInfo({
success: function(res) {
console.log(res.userInfo)
}
})
}
}
})
},

新建 Node.js 云函数 login

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//  调用云函数
wx.cloud.callFunction({
name: 'login',
success:res =>{
userInfo.openid = res.result.openid
this.setData({
userInfo,
hasLogin:true
})
app.login(userInfo)
},
fail:error=>{
console.log(error);
}
})

微信小程序云开发官方文档

基础

介绍

云开发可以开发微信小程序、小游戏,无需搭建服务器环境,即可使用云端能力。云开发提供了完整的原生云端支持和微信服务支持。

云开发提供基础能力

  • 云函数
  • 数据库
  • 存储
  • 云调用
第一个云开发小程序

快速使用云开发

  1. 新建云开发模板
  • 无游客模式、也不可以使用 测试号
  • project.config.json 中增加了字段 cloudfunctionRoot 用于指定存放云函数的目录
  • cloudfunctionRoot 指定的目录有特殊的图标
  • 云开发能力从基础库 2.2.3 开始支持(覆盖率 97.3%,查看兼容性问题)
  • 从基础库 2.4.1 开始,在小程序插件中可以使用云开发。
  1. 开通云开发
  2. 体验小程序
  3. 查看控制台
  • 运营分析:查看云开发监控、配额使用量、用户访问情况
  • 数据库:管理数据库,可查看、增加、更新、查找、删除数据、管理索引、管理数据库访问权限等
  • 存储管理:查看和管理存储空间
  • 云函数:查看云函数列表、配置、日志
云开发能力

数据库

关系型 文档型
数据库 database 数据库 database
表 table 集合 collection
行 row 记录 record / doc
列 column 字段 field

集合数据示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[
{
"_id": "Wzh76lk5_O_dt0vO",
"title": "The Catcher in the Rye",
"author": "J. D. Salinger",
"characters": [
"Holden Caulfield",
"Stradlater",
"Mr. Antolini"
],
"publishInfo": {
"year": 1951,
"country": "United States"
}
},
{
"_id": "Wzia0lk5_O_dt0vR",
"_openid": "ohl4L0Rnhq7vmmbT_DaNQa4ePaz0",
"title": "The Lady of the Camellias",
"author": "Alexandre Dumas fils",
"characters": [
"Marguerite Gautier",
"Armand Duval",
"Prudence",
"Count de Varville"
],
"publishInfo": {
"year": 1848,
"country": "France"
}
}
]

id 字段用以唯一标志一条记录
_openid 字段用以标志记录的创建者

数据库 API 分为小程序端和服务端,小程序端有限制。
数据库 API 包含增删改查的能力,使用 API 操作数据库

  • 获取数据库引用
  • 构造查询/更新条件
  • 发出请求
1
2
3
4
5
6
7
8
9
10
11
12
13
// 1.获取数据库引用
const db = wx.cloud.database();
// 2.构造查询语句
db.collection('books').where({
publishInfo: {
country: 'United States'
}
}).get({
success: function(res) {
// 输出 [{ "title": "The Catcher in the Rye", ... }]
console.log(res)
}
})

存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wx.chooseImage({
success: chooseResult => {
// 将图片上传至云存储空间
wx.cloud.uploadFile({
// 指定上传到的云路径
cloudPath: 'my-photo.png',
// 指定要上传的文件的小程序临时文件路径
filePath: chooseResult.tempFilePaths[0],
// 成功回调
success: res => {
console.log('上传成功', res)
},
})
},
})

云函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// index.js 是入口文件,云函数被调用时会执行该文件导出的 main 方法
// event 包含了调用端(小程序端)调用该函数时传过来的参数,同时还包含了可以通过 getWXContext 方法获取的用户登录态 `openId` 和小程序 `appId` 信息
const cloud = require('wx-server-sdk')
exports.main = (event, context) => {
let { userInfo, a, b} = event
let { OPENID, APPID } = cloud.getWXContext() // 这里获取到的 openId 和 appId 是可信的
let sum = a + b

return {
OPENID,
APPID,
sum
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
wx.cloud.callFunction({
// 需调用的云函数名
name: 'add',
// 传给云函数的参数
data: {
a: 12,
b: 19,
},
// 成功回调
complete: console.log
})
// 当然 promise 方式也是支持的
wx.cloud.callFunction({
name: 'add',
data: {
a: 12,
b: 19
}
}).then(console.log)
重要概念

资源环境

建议每一个正式环境都搭配一个测试环境,建议一个创建为 test 测试环境,一个创建为 release 正式环境。

配额

插件支持

从基础库 2.4.1 开始,在小程序插件中可以使用云开发。

多端支持

云开发除了支持小程序端 SDK、云函数端 SDK 访问外,从 06/04 起支持 Web 端 SDK 访问。

未登录模式

开发指引

控制台

云开发控制台

  • 概览:查看云资源的总体使用情况
  • 用户管理:查看小程序的用户访问记录
  • 数据库:管理数据库集合、记录、权限设置、索引设置
  • 存储管理:管理云文件、权限设置
  • 云函数:管理云函数、查看调用日志、监控记录
  • 统计分析:查看云资源详细使用统计
初始化

小程序端初始化

1
2
3
wx.cloud.init({
env: 'test-x1dzi' // env 设置只会决定小程序API 调用的云环境
})

云函数端初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})

exports.main = async (event) => {
const { ENV, OPENID, APPID } = cloud.getWXContext()

// 如果云函数所在环境为 abc,则下面的调用就会请求到 abc 环境的数据库
const dbResult = await cloud.database().collection('test').get()

return {
dbResult,
ENV,
OPENID,
APPID,
}
}

相关资料
Web云开发快速开始
Serverless 掀起新的前端技术变革
小程序云开发

30分钟创建并上线小程序项目

云开发自动化索引的设计与实现
新能力丨报告,邮箱登录已支持!
海量数据热迁移,小程序云开发数据库这样做
实战丨云开发帮你和「火箭少女」合个影!
实战丨基于云开发实现的外卖小程序
如何用Cloudbase Framework部署一个Vue项目?
实战丨用云开发快速构建信息申报小程序
用云开发实现的开源的外卖小程序,现在来啦
如何用云开发打造“万人同屏”高并发实时互动小程序
几行代码搞定智能插座控制丨云开发 × 涂鸦
小程序云开发数据库核心能力解析及最佳实践
浅析小程序云原生数据库设计与应用

云开发 Serverless 从入门到实战

http://example.com/2020/07/29/Blog-about-learning-121/

作者

Fallen-down

发布于

2020-07-29

更新于

2020-09-02

许可协议

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.
You need to set client_id and slot_id to show this AD unit. Please set it in _config.yml.