Serverless 架构与微信小程序云开发实践总结
接了一个小程序需求,页面写完只花了两天,真正卡住我的是后面那一半:买服务器、配 Nginx、申请域名、写登录鉴权、建数据库表。前端的活干完了,后端的活才刚开始。后来这个项目整体换成了小程序云开发,上面那堆步骤一个都没做,业务代码直接跑在云上,登录态还是平台白送的。
这篇是我把 Serverless 从概念到落地重新捋了一遍的笔记。里面既有原理部分,比如 FaaS 和 BaaS 的分工到底在哪、冷启动为什么慢;也有大量实操截图,从小程序云开发环境配置一路走到部署管理后台。跟着点基本能走通。
在本篇文章中,我们将从浅入深,和大家一起学习以下知识:
- Serverless 到底是什么,狭义和广义的两种说法分别指什么
- FaaS 与 BaaS 的分工,以及事件驱动、单事件处理、自动伸缩、无状态这四个技术特点
- 冷启动的来龙去脉,FaaS 的三层结构,以及 SFF 这种前端用法
- 传统架构和 Serverless 架构的对比,优势在哪、什么场景不适合
- 微信小程序云开发的环境创建、环境 ID 配置、云函数部署上传
- 云函数实战场景:获取 openId、生成小程序码、图片上传、tcb-router 路由、订阅消息、定时触发器
- 云数据库的 100 条限制突破、分页、模糊查询、权限管理、一对多建模
- 云函数调试:控制台调试与 VS Code 本地调试
- 用 HTTP API 从外部服务触发云函数,搭一个管理后台
- 腾讯云 Web 函数、Serverless Framework 部署前后端项目、连接 MySQL
- 云开发(CloudBase)和 Serverless Framework 的区别,以及阿里云、Vercel 的部署方式
这篇写于 2021 年,微信开发者工具和云开发控制台后来都改过版,文中的截图和菜单位置可能和你现在看到的不完全一样。原文的截图我一张没删,操作思路是通用的,具体入口以你打开的实际界面为准。
# 一、Serverless 到底是什么
先看几张图,把这个词的边界圈出来。

这两张图想说的是同一件事:你写的还是那份业务代码,变的是这份代码运行在谁的机器上、由谁负责把它拉起来。

看完这几张图,有个最容易踩的误解要先排掉:Serverless 不是「没有服务器」。
我们使用函数的时候不用关心后端IP、域名,只需要调用函数,后端的服务是一个函数。serverless并不是没有服务器,只是服务器部署在云上面的,比我们去自己维护更方便多
Serverless又名无服务器,所谓无服务器并非是说不需要依赖和依靠服务器等资源,而是开发者再也不用过多考虑服务器的问题,可以更专注在产品代码上。Serverless是一种软件系统架构的思想和方法,它不是软件框架、类库或者工具。它与传统架构的不同之处在于,完全由第三方管理,由事件触发,存在于无状态(Stateless)、 暂存(可能只存在于一次调用的过程中)计算容器内。构建无服务器应用程序意味着开发者可以专注在产品代码上,而无须管理和操作云端或本地的服务器或运行时(运行时通俗的讲 就是运行环境,比如nodejs环境,java环境,php环境)。Serverless真正做到了部署应用 无需涉及基础设施的建设,自动构建、部署和启动服务。
- 第一种:
狭义 Serverless(最常见)=Serverless computing 架构=FaaS 架构=Trigger(事件驱动)+ FaaS(函数即服务)+ BaaS(后端即服务,持久化或第三方服务)=FaaS + BaaS- 第二种:广义
Serverless=服务端免运维=具备 Serverless 特性的云服务
平时大家嘴上说的基本都是第一种。第二种范围太宽,宽到对象存储、消息队列都能算进去,讨论的时候容易鸡同鸭讲,所以先约定好说的是哪一种再往下聊。

- FAAS:函数即服务,通俗来说就是我们可以写一个函数,在该函数内执行业务逻辑,函数由 FaaS 平台运行
- BAAS:后端即服务,通常指云服务,该云服务常指中间件服务
FAAS+BAAS 构成了Serverless架构
下面这张图把整条链路画完整了,可以对着看一遍请求是怎么走的。

整体架构十分简单明了, 用 FC 替代了 Web 服务器,但是换来的是免运维,弹性扩容,按需付费等一系列优点
图里那个 FC 就是函数计算(Function Compute),它站在了原来 Nginx + Node 进程的位置上。少掉的不是服务器,是那台服务器带来的一整套活:装环境、配进程守护、盯 CPU 曲线、半夜起来扩容。
目前,Serverless 的应用场景广泛,大部分传统业务均可以在 Serverless 云函数上完美支持
# Serverless 要解决什么
问题:前端和后端分离后,彼此独立,这样就导致前端需要关注一些后端关注的问题,如下。
- 完整的后端应用上线流程
- 机器管理运维:扩缩容
- 降级、熔断、限流
- 域名、性能、监控
是不是触及了很多同学的知识盲区。作为一个前端,确实大多数人对于服务端的环境,部署基础设施等等东西并不了解。但是现在前端是独立的部署,前端必然面临这些东西。这就是serverless要解决的问题。
这几条我自己是真的一条条撞过来的。前后端分离之后,前端产物要独立部署,那域名、证书、CDN 回源、灰度就都落到前端头上了。再往前一步做 SSR 或者 BFF,限流和熔断也躲不掉。写业务的人被迫先变成半个运维,这才是痛点所在。
# Serverless 做什么事
问题:是不是可以弄一个工具,我们只需要关心前端代码,服务器的东西工具自动帮我们做好。
这就是serverless做的事情。如下图,我们只需要关心业务代码,不需要关心服务器的基础设施。

图里灰色的那部分是云厂商接管的边界。你交出去的是运维控制权,换回来的是不用管它。这笔交易划不划算,取决于你的业务是不是真的需要那些控制权,后面讲不足的时候会展开。
# Serverless 和函数计算的区别
这两个词经常被混着用,其实不是一个层级的东西。函数计算是产品,Serverless 是理念。

对着图记一句话就够了:函数计算是实现 Serverless 的一种方式,但用了函数计算不代表你的架构就是 Serverless 的,如果背后还挂着一台你自己运维的 MySQL,那运维成本只是挪了个位置。
# 二、Serverless 的四个技术特点
这四个特点不是并列的四条知识点,它们是一环扣一环推出来的:因为事件驱动,所以能做到单事件处理;因为单事件处理,弹性伸缩才好做;因为要弹性伸缩到 0,函数就必须无状态。理解了这条链,后面遇到的很多限制就都能自己推出来。
事件驱动
- 云函数的运行,是由事件驱动起来的,在有事件到来时,云函数会启动运行
- Serverless 应用不会类似于原有的「监听 - 处理」类型的应用一直在线,而是按需启动
- 事件的定义可以很丰富,一次 http 请求,一个文件上传,一次数据库条目修改,一条消息发送,都可以定义为事件

和传统 Node 服务对比一下就很清楚了。app.listen(3000) 起来之后进程一直挂着,没请求也占内存;云函数是没事件的时候一个实例都不留。这也是为什么按调用次数计费在低频场景下能便宜到接近免费。
单事件处理
- 云函数由事件触发,而触发启动的一个云函数实例,一次仅处理一个事件
- 无需在代码内考虑高并发高可靠性,代码可以专注于业务,开发更简单
- 通过云函数实例的高并发能力,实现业务高并发

这一条对写代码的人影响挺大。传统 Node 服务是单进程处理并发请求,你得小心模块级的可变变量被多个请求串改;云函数一个实例一次只吃一个事件,天然没有这个问题。但反过来也有坑:模块级缓存在实例复用的时候还在,实例销毁重建就没了,所以别拿它当可靠缓存用。
自动弹性伸缩
- 由于云函数事件驱动及单事件处理的特性,云函数通过自动的伸缩来支持业务的高并发
- 针对业务的实际事件或请求数,云函数自动弹性合适的处理实例来承载实际业务量
- 在没有事件或请求时,无实例运行,不占用资源

这里有个坑要注意:并发实例是有账号级配额上限的,突然的流量尖峰不是无限扩容。后面讲小程序云函数计费的时候会看到具体的配额数字。
无状态开发
- 云函数运行时根据业务弹性,可能伸缩到 0,无法在运行环境中保存状态数据
- 分布式应用开发中,均需要保持应用的无状态,以便于水平伸缩
- 可以利用外部服务、产品,例如数据库或缓存,实现状态数据的保存

无状态这条最容易在写老代码迁移的时候翻车。像用 express-session 默认的 MemoryStore 存会话、往 /tmp 写文件当持久化、用全局变量做计数器,这些在云函数里全都不成立。状态要么进数据库,要么进 Redis,要么走对象存储。
# 三、传统架构和 Serverless 架构的对比
先看传统的开发模式长什么样。

三张图连起来看,重点是中间那一大段:买机器、装环境、部署、配负载均衡、上监控。这段活跟你的业务逻辑一点关系都没有,但每个项目都得重做一遍。
再看换成 Serverless 之后的样子。

正常来说,用户开发 Server 端服务,常常面临开发效率,运维成本高,机器资源弹性伸缩等痛点,而使用 Serverless 架构可以很好的解决上述问题。下面是传统架构和 Serverless 架构的对比:

这张对比表建议存下来。做技术方案评审的时候,甲方最关心的往往不是技术优雅不优雅,而是这两栏里的成本和上线周期。
云函数计算是一个事件驱动的全托管计算服务。通过函数计算,您无需管理服务器等基础设施,只需编写代码并上传。函数计算会为您准备好计算资源,以弹性、可靠的方式运行您的代码,并提供日志查询,性能监控,报警等功能。借助于函数计算,您可以快速构建任何类型的应用和服务,无需管理和运维。
# 四、Serverless 的优势和不足
优势
- 无运维:我们不需要购买服务器,直接可进行
- 资源分配: 在
Serverless架构中,你不用关心应用运行的资源(比如服务配置、磁盘大小)只提供一份代码就行。 - 计费方式: 在
Serverless架构中,计费方式按实际使用量计费(比如函数调用次数、运 行时长),不按传统的执行代码所需的资源计费(比如固定CPU)。计费粒度也精确到了毫 秒级,而不是传统的小时级别。个别云厂商推出了每个月的免费额度,比如腾讯云提供了每 个月 40 万 GBs 的资源使用额度和 100 万次调用次数的免费额度。中小企业的网站访问量不 是特别大的话完全可以免费使用。
计费这块的额度是会调整的,下面这张图是我当时截的,具体数字以你打开控制台看到的为准。

GBs 这个单位第一次看容易懵,它是「内存规格乘以运行时长」。一个配 128MB 内存的函数跑 1 秒,消耗的是 0.125 GBs。所以省钱的方向有两个,一是把函数内存调小,二是把执行时间压短,两者是相乘的关系。
- 弹性伸缩:
Serverless架构的弹性伸缩更自动化、更精确,可以快速根据业务并发扩容更 多的实例,甚至允许缩容到零实例状态来实现零费用,对用户来说是完全无感知的。而传统 架构对服务器(虚拟机)进行扩容,虚拟机的启动速度也比较慢,需要几分钟甚至更久。
不足
当然了 ServerLess 是很诱人,但却不是万能的,有些场景还是不适合的。
- ServerLess 不仅仅是一门技术也是一种理念和微服务一样,很多老系统不能直接上 ServerLess,得相应的进行升级和拆解才能更好的适应 ServerLess,这是一个门槛。
- 同时 ServerLess 针对开发语言的可定制性和可开放性,ServerLess 会选择处于稳定版的语言且更新具有一定的滞后性,特别是 Node.JS 这样的版本更新帝,最新稳定版是10,但是提供的却是8。同时如果对语言有底层的修改而无法通过 Plugin 实现同样也无法适应相关场景。
- 不适合长时间的进行计算处理的场景,ServerLess 是产生计算后按时间计费的,适合那些触发类短时间计算的,如果有长时间进行计算的场景就不适合。