近两年来,Serverless 无疑是前端圈里最火热的话题之一,在各种技术峰会、各种技术文章里都能看到它的身影。如果你是一名前端开发者,一定很奇怪:
“我们这些前端切图仔,为什么要关注 Serverless 这种云计算的概念?”
我们就从这个话题开始聊起吧。
这个问题用一句话回答就是:
“Serverless 解放了端开发者(不仅仅是 Web 开发者)的生产力,让端开发者可以更快、更好、更灵活地开发各种端上应用,不需要投入太多精力关注于后端服务的实现。”
下面我们就来慢慢解释这句话。
在前端的史前时代,那个时候甚至还没有”前端工程师“这个职位分类,所有人都是后台开发,所有的网页和 Web 应用都是来自于后台渲染,CGI、PHP (甚至你可能都没听说过的 Perl)便是当时 Web 技术的代名词,那个时候的 JS 和 CSS,不过是“切图仔”在网页里写动效和弹窗的小玩具而已。
后来,AJAX 技术出现了,最早在 Outlook Web Access 中出现,随后随着 Google Map、Gmail 等大型 Web 应用的实践,逐步为人所知。这项技术让页面内的 JS 也能异步地向服务器发起各种请求,并且把数据渲染到页面上。这个时候,前端工程师们开始接管视图层逻辑:
再后来,Node.js 诞生,大大降低了前端开发者开发一个后台服务的难度,这也让前端开发者逐渐接管了接管了渲染逻辑,在这期间,各大前端框架(代表性的 React、Vue)的服务器端渲染也逐步成熟。
既然能用 Node.js 来做服务端渲染,那么拿 Node.js 来写后台业务逻辑、实现各种 HTTP API 当然也不在话下,所以在一些公司里,前端接管业务逻辑,后台只负责各种底层微服务的架构就出现了,这也是目前很多大公司在实行的架构:
细心的你可能已经注意到了,在这个时候,渲染、HTTP API、后台业务逻辑这些东西,从端的角度看是属于服务端的,但是从分工角度看却属于前端开发的范畴,这就是 BFF(Backend for Frontend)的概念,它的优势在于:
这就是为什么大公司的很多业务,都开始越来越多地招 Node.js 全栈工程师的原因。
但是 BFF 并不是银弹,它还是有一定问题的,比如在国内通晓前后端开发的全栈工程师太少,很难撑起大体量的业务开发。而且国内大多数前端工程师缺少服务端开发的经验,让他们运维上百台服务器和一整套海量服务,有点强人所难:
而 Serverless 正是帮助前端工程师解决运维开发 BFF 的良药。
Serverless 这个单词,直译成中文的话,应该是“无服务器”。当然,这里的“无服务器”绝对不是说不需要任何服务器资源了,而是说不需要关心服务器的具体运维和管理,只需要写代码然后发布即可。
它包含了 FaaS(函数即服务)和 BaaS(后端即服务)两大块功能,把各种基础设施进行了抽象,即使不熟悉后端的开发者,也能快速高质量地开发出海量、稳定的后端服务,而这对于前端工程师维护 BFF 服务来说,几乎是量身定做的。
举一个最简单的例子,你现在需要上线一个新的 HTTP API(比如 /getUser?id=123
),如果使用 Serverless 服务的话,有多快呢?
你只需要写下面这个云函数:
module.exports = async function(events, context) {
const { id } = events.query.id
const userInfo = await fetchUserInfo(id) // 调用后端微服务,拉取用户信息
return userInfo
}
然后发布这个云函数(假设命名为 getUser
),并且为它设置一条路由:
cloudbase service:create -f getUser -p /getUser
然后你就可以通过 https://xxx.com/getUser
来拉取数据了,同时还附赠海量弹性伸缩、异地多活、日志监控等多方位的能力。
如果你觉得这样很酷炫,那么不如来试一试 云开发 Cloudbase 吧!
云开发(Cloudbase)是腾讯云 TCB 团队(Tencent Cloudbase)出品的云端一体化产品方案,为广大的小程序、Web、移动端开发者提供一站式的 Serverless 服务。
当然这是官方的说法,用人话讲就是:
用了云开发,各个端的开发者就可以一站式地解决后端服务问题了!
实际上早在 2018 年,云开发就联合微信团队推出了 「小程序·云开发」,如果你对它还不怎么了解,可以看这两篇文章:
而现在,云开发 For Web 也正式上线了!
云开发提供了云数据库、云函数、云存储、用户登录体系等一系列的后端能力,并且提供了各端的 SDK,让各个端的开发者能够基于这些能力,快速、优质地开发出功能丰富的应用。
Talk is cheap, Show me the code!
口说无凭,我们还是来直接看代码吧!
云开发提供了一个文档型的 NoSQL 数据库,与传统的云上数据库不同的是,云开发的数据库可以在各种客户端内使用 SDK 直接进行读写,比如 Web 应用、小程序内、Flutter 客户端等等。
下面我们以 Web 应用为例,展示云数据库的一系列功能。
CURD 是数据库最基础的功能,云开发 SDK 提供了一套链式调用接口,对数据库进行读写:
// 使用 Web 端 SDK
const cloudbase = require('tcb-js-sdk')
const app = cloudbase.init({ /* 初始化... */ })
const db = app.database()
// 插入文档
await db.collection('messages').add({
author: 'stark',
message: 'Hello World!'
})
// 查询文档
const data = await db.collection('messages').where({
author: 'stark'
}).get()
// 更新文档
await db.collection('messages').where({
author: 'stark'
}).update({
message: 'Hi, Cloudbase!'
})
// 删除文档
await db.collection('messages').where({
author: 'stark'
}).remove()
普通的查询可能无法满足一些复杂的需求,比如联表、group 等等。
云开发针对这些复杂的查询场景,推出了聚合搜索的功能,把一系列操作抽象为一个管道(pipeline),单次执行即可,避免了多次读的性能问题,我们以 group 操作为例:
const $ = db.command.aggregate
const result = await db
.collection('message')
.aggregate()
.group({
// 以 author 字段作为 key,统计相同 author 的数量
_id: '$author'
messagesCount: $.sum(1)
})
.end()
//=> { "_id": "stark", messagesCount: 12 }
更多的聚合搜索功能,可以参考: Aggregate | 云开发 Cloudbase
在订票、预约、转账等等场景下,开发者可能会要求数据库能够保证一连串读写的原子性,避免出现竞争条件,这就是数据库事务的使用场景。
云开发数据库当然也提供了事务功能:
// 启动事务
const transaction = await db.startTransaction()
// 在事务内读
const data = await transaction.collection('messages')
.where({ /* <query> */})
.get()
// 在事务内写
await transaction.collection('messages')
.where({ /* <query> */})
.update({ /* <data> */})
// 提交事务
await transaction.commit()
在实时聊天室、实时数据看板等等场景下,我们经常会需要订阅数据库的更新,从而实现实时数据推送。
云开发的数据库提供的 watch()
方法就是为此设计的,每当数据库符合条件的文档发生变化时,都会触发 onChange
回调,示例代码如下:
await db.collection('messages')
.where({/* <query> */})
.watch({
onChange: snapshot => {
console.log("收到snapshot!", snapshot)
},
onError: error => {
console.log("收到error!", error)
}
})
更多信息可以参考: 数据库实时推送 | 云开发 Cloudbase
所谓的云函数,便是在云端运行的、事件驱动的一段代码,它可以被 SDK 调用,也可以直接通过 HTTP 调用,还可以设置定时器让它定期运行:
// sum.js
module.exports = async function(events) {
return events.a + events.b
}
这一小段代码很简单,但是隐藏在它之下的却是一整套庞大的 FaaS(函数即服务)基础设施,提供了诸如弹性伸缩、日志、监控告警等多方面的能力。
使用云开发的客户端 SDK,可以轻而易举地在各个端上调用云函数,我们以 Web 应用为例:
const cloudbase = require("tcb-js-sdk");
const app = cloudbase.init({/* 初始化 */});
app.callFunction({
// 云函数名称
name: "sum",
// 传给云函数的参数
data: {
a: 1,
b: 2
}
})
.then(res => {
console.log(res); // 输出 "3"
})
.catch(error);
你也许会觉得 SDK 体积庞大,太沉重了,那么你也可以选择使用 HTTP 来调用云函数,响应 HTTP 请求。
// hello.js
module.exports = function() {
return 'Hello, World!'
}
然后我们直接通过命令行发布这个函数,并为它创建一条路由:
$ cloudbase functions:deploy hello
$ cloudbase service:create -f hello -p /hello
随后便可以通过 url 直接访问这个云函数:
$ curl https://xxx.service.tcloudbase.com/hello
Hello, World!
具体可以参考: https://docs.cloudbase.net/service/quick-start.html
在 Cloudbase 的云函数内,你可以直接使用 Node.js SDK,无需在初始化的时候额外注入秘钥:
const cloudbase = require('@cloudbase/node-sdk')
// 无需使用服务端秘钥
const app = cloudbase.init()
const data = await app.database().where().get()
更详细的内容可以参考: https://docs.cloudbase.net/api-reference/server/node/initialization.html
我们在开发应用的过程中,经常会遇到图片、文件上传的需求,并且可能需要为这些文件设置 CDN 访问。传统的流程是下面这样的:
但如果使用云开发,只需要在客户端调用 uploadFile
,就可以一步完成上面的三件事情:
const tcb = require("tcb-js-sdk");
const app = tcb.init({
env: 'your-env-id'
})
const { fileID } = await app.uploadFile({
// 云端路径
cloudPath: "/a/b/c/filename",
// 需要上传的文件,File 类型
filePath: document.getElementById('file').files[0]
})
uploadFile
会返回一个 fileID
,是云开发内文件的唯一标识符,我们可以使用 getTempFileURL
来获取文件 URL 访问链接:
const tcb = require("tcb-js-sdk");
const app = tcb.init({
env: 'your-env-id'
})
const { fileList } = app.getTempFileURL({
fileList: [
'cloud://a/b/c'
]
})
// fileList 是一个有如下结构的对象数组
// [{
// fileID: 'cloud://a/b/c', // 文件 ID
// tempFileURL: 'http://xxx/xxx/xxx', // 临时文件网络链接
// maxAge: 120 * 60 * 1000, // 有效期
// }]
更详细的内容,可以参考: https://docs.cloudbase.net/storage/introduce.html
云开发除了上述的基础功能之外,还提供了一系列的扩展能力,包括但不仅限于:
更详细的内容,可以参考: https://docs.cloudbase.net/extension/introduce.html
上面的能力是不是有些让你看花眼了,完全不知道要怎么搭配起来使用?
其实一张图就可以解决:
图中的客户端 SDK 包括:
wx.cloud
中)服务端 SDK 包括:
光看示例代码当然没有什么意思,我们接下来就拿云开发的一些能力,来快速开发一个实时在线聊天室吧。
项目代码: https://github.com/TencentCloudBase/cloudbase-realtime-demo
这是一个由 create-react-app
快速生成的脚手架项目,所以大部分构建和工程化的细节这里就略过不谈了,我们直接来看代码实现,大致上实现了三个功能,括号中是使用的云开发能力:
首先是我们的初始化流程,先使用 匿名登录,然后建立 实时数据推送的连接:
async function init() {
// 使用匿名登录
await auth.anonymousAuthProvider().signIn();
// 使用 refreshToken 的前 6 位作为 uid
setUid(auth.hasLoginState().credential.refreshToken.slice(0, 6));
// 建立实时数据推送连接
await db
.collection("messages")
.where({})
.watch({
onChange(snapshot) {
setList(snapshot.docs);
setLoading(false);
},
onError(err) {
console.log(err);
},
});
}
建立实时连接之后,集合中的任何变化,都会触发 onChange()
回调,然后我们使用 setList()
来更新界面上的消息数据。
当然只读消息是不够的,我们还需要发送消息,具体实现非常简单,可以看 sendMessage()
方法,直接使用 add()
方法向数据库写入数据就可以了:
// 发送消息
async function sendMessage() {
const message = {
timestamp: new Date().getTime(),
text,
uid,
};
await db.collection("test").add(message);
// 清空输入栏
setText("");
}
当然以上只是局部的代码片段,整体代码可以参考:
https://github.com/TencentCloudBase/cloudbase-realtime-demo/blob/master/src/App.js
开发完毕之后,我们便可以使用 云开发静态网站 来托管我们的这个聊天室 Web 应用。
首先我们构建我们的应用:
$ npm run build
构建产物会生成到 build
目录下。
然后我们发布到静态托管即可(托管前,请先 开通静态网站):
$ cloudbase hosting:deploy ./build -e your-env-id
发布完成后,你便可以通过 https://xxxx.tcb.qcloud.la/xxxx
的来访问你的应用了。进一步,你还可以为它 绑定自定义域名。
PS:实际上,云开发的 主页和 官方文档,就是这样托管的(毕竟做云服务的,最重要的就是 Eating your own dog food 嘛)。
当然,除了这个实战 Demo 以外,还可以看看一些真正业务的实践:
给 Web 开发者带来效率和质量上的提升,帮助他们开发更多更优质的应用,免去运维、后台开发的烦恼,是云开发不变的愿景。虽然我们目前已经有了很多强大又方便使用的能力,但这远不是我们的终点(实际上我们才刚刚起步),在未来我们将会持续完善下面的能力,进一步完善云开发的体系:
PS:如果你觉得这篇文章对你有帮助,不妨花几分钟时间,来试一试 快速开始吧。
PHP网站源码南山设计公司网站深圳品牌网站设计南澳阿里店铺运营东莞网站优化按天收费双龙关键词按天收费宝安网站建设大芬百搜词包龙华网站优化软件龙华关键词排名包年推广惠州外贸网站建设南澳建网站南联seo塘坑外贸网站建设民治百度爱采购永湖建网站坂田企业网站制作惠州建站罗湖关键词排名包年推广坪地网站搭建横岗优化民治英文网站建设宝安英文网站建设沙井营销型网站建设深圳网站建设横岗seo网站推广大鹏百度标王大鹏百度seo盐田网站开发东莞外贸网站设计塘坑SEO按效果付费歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运