作者介绍
陈天忱,IMWEB团队成员,腾讯前端开发工程师, 主要负责腾讯课堂小程序,腾讯课堂直播间等业务模块。
首先介绍下腾讯在线教育下的3个主要业务:
- 针对成人职业化,兴趣化学习的腾讯课堂;
- 针对小学,初高中k12领域的企鹅辅导;
- 针对少儿英语学习的ABCMouse。
这3块业务都在Web端、小程序端和客户端都有落地产品,以满足不同端的用户需求。
随着业务的高速发展,在小程序端,我们部门对应的小程序有十几个,而且还可能推出更多工具类、平台类的小程序。众多的小程序业务,意味着频繁的业务需求,为了保障业务的稳定及效率,我们团队在小程序的同构、CI、云开发等领域都进行了积极的尝试,并取得了不错的成果。
面对频繁的业务需求,我们作为一个前端团队,一直在思考否能有更多的发挥空间,而云开发的出现,恰恰助力我们拓展前端的边界。
下面以腾讯课堂小程序为例,为大家介绍我们在小程序云开发上的实践。
如何实现多个小程序,
多端共用同一个云开发环境
2018年,微信小程序和云开发ClouBase两个团队深入合作推出小程序云开发,为每一个小程序都提供了一个非常简洁方便的小程序云开发的入口,弱化后端和运维概念,无需搭建服务器。
但是我们在开始使用云开发的时候遇到了一个问题:我们多个小程序需要使用同一个云开发环境,这样一些通用的平台能力可以复用。但是在小程序云开发中,每个小程序使用内置的sdk只能调用小程序账号自身关联的云开发环境,这样的话,云函数的代码就要维护多套。显然这并不是我们想要的,内置的sdk并不能满足我们的需求。况且我们的H5和PC端要用云开发的话,又得另外维护一个环境。
我们有想过通过Node走http调用,但是通过网关-node-具体服务,自行搭建又会面临容灾、运维、扩容,这又失去了云开发的意义。
当然,我们的H5和PC也可以使用小程序账号的云开发环境,但依然不能解决不同小程序之间公用云开发环境的问题。
所以在最初,我们尝试用serverless来解决这个问题,即把接入层换成API网关,就可以满足需求。但是,当我们接入API网关来使用云开发的能力时,走网关调用,这时鉴权这一块就得走业务自身鉴权了,无法使用小程序云开发天然免鉴权的便利。
所以我们和云开发团队深度合作,推出了用于小程序端的Web SDK,这样多端调用得以实现。事实上,tcb-js-sdk-mp和内置sdk一样,提供了免鉴权等多种鉴权方式,我们可以像使用内置sdk那样拿到用户的openid,节约开发成本。
如果你们的业务也有同样的问题,可以参考下。
这里是我们使用tcb-js-sdk-mp的一部分代码演示:
初始化略有不同,初始化这里要跟tcb-js-sdk一样,调用对应的api去校验登录态。然后函数调用这里因为不是直接访问内置的环境,还是需要做一个域名限制,防止被刷。封装了云函数调用方法,进行了初始化,后续的操作就跟使用内置的sdk没什么区别了。
通过云开发CLI工具构建
函数自动化部署管理(CI)流程
涉及到一个新的环境,就要面对部署的问题。
常用的云函数部署方式是通过开发者工具,但是通过工具右键部署会有一些问题,比如手动选择环境,容易出错,严重的可能造成现网事故;依赖环境,内网包无法在线安装,本地上传可能有些包有平台特性 ( docker挂在安装特定环境依赖)。
不过这些都可以通过一个现有的工具得到解决。云开发提供了CLI工具用于云函数的操作,包括登录、初始化、部署函数、触发函数等,有了这个工具,我们的云函数完全可以另起项目单独开发了,和小程序项目进行分开管理。并且cli提供了灵活的配置,超时时间,环境变量,私有网络,是否安装依赖等功能。
我们依赖cloudbase-cli配置了一套云函数部署的CI流程,通过不同的方式来触发CI,就可以将函数部署到不同的环境中来,减少人工手动部署可能带来问题的风险。并且这里可以看到,像我们的业务会希望有一个预发布环境,不使用小程序内置的云开发环境,就可以突破两个环境的限制。
运用云开发数据库的
事务能力实现以老带新活动
下面,我就分享一个我们业务中,对于云数据库实际的场景应用。
我们有一个大促的活动,需要学员邀请用户参加,就可以领取一些精品课程,来促使互动的传播,需要用到小程序一个动态消息的能力。每个用户能够邀请的用户有限制,如果活动过期了,将会展示一个已结束的状态。点开可以给活动发起者助力,不能重复,满员时不能继续助力。因为这个页面功能不涉及特别复杂的数据操作,比较简单。我们觉得这个功能就非常适合前端用云开发来实现,可以节省一些后端的人力。
先从建表开始。很简单,一个表,当邀请到用户参加活动时,往goups里面添加一个用户,并更新动态消息,当用户数达到上限时则不再添加。但是这种活动往往会伴随着并发的操作,如何保证并发时数据的准确性,就需要我们对操作的数据上锁,避免同时操作导致被覆盖。
所以需要用到云数据库的事务能力。
我们另外又维护了一个表,用于记录被邀请的名额信息,在事务中对名额进行操作,事务完成则去更新状态,否则就可能进行事务的回滚。
下面具体看下整个操作的过程
一、在活动页面,用户点击开启活动生成一个活动id。这个生成活动id的方法是小程序端和云开发这边都支持的一个生成动态消息id的方法,可以直接用这个作为一个活动的id了。
二、同步创建对应上限人数的人员位,所有的状态都是空的。这样一个活动就创建好了
三、如果有人点击进入活动页面,先通过活动id获取到对应的活动数据;然后根据云开发天然无鉴权的特性直接在云函数里面拿到用户的信息,再根据用户的信息及活动数据来判断是否有助力的权限。
比如这是你发起的活动,那么就只会展示已邀请到的人数,如果过期了就展示过期,还有你已经助力过了,或者名额已经满了等等,这个就是具体的业务逻辑了,不细讲,我们就给一个disable的页面。如果有就给一个正常的页面。
用户点击助力,则通过事务从对应的活动位取出一个空的活动位,并对活动位进行更新,这时候这个活动位就被上了事务锁。这时,如果有另一个用户同时并发的去修改这个活动位,则会直接失败,那么就可以尝试去占用下一个空位。
依次尝试占用所有的空位都失败了,就反馈该活动团已满。
正常的情况下,就可以直接进行更新操作,并将user字段改为此用户的信息,标记为已占用状态。事务跑过后再将用户的信息 push到活动数据的groups字段内,并判断是否已满员。完成更新后就可以结束事务,然后完成后续的动态消息更新的操作。
在这个过程中如果出现了错误,我们都可以对事务进行回滚,来保证数据的准确性。
小程序云开发的出现,让我们前端团队有了更广阔的发挥空间,也让我们得以更迅速地响应运营推广需求。关于小程序云开发的运用技巧,有许多地方值得我们去挖掘,欢迎大家一起来交流学习。