小程序云函数开发实践

随着业务的高速发展,我们团队在小程序端对接的业务越来越多也越来越繁杂。面对繁杂的业务需求,我们作为一个前端团队,一直在思考否能有更多的发挥空间,而云开发的出现,恰恰助力我们拓展前端的边界。

本文将主要记录我们团队在小程序云函数中的开发实践。

什么是云函数?

云函数(FaaS)是一段运行在云端的、轻量的、无关联的、并且可重用的代码。无需管理服务器,只需编写和上传代码,即可获得对应的数据结果。使用云函数可以使企业和开发者不需要担心服务器或底层运维设施,可以更专注代码和业务本身,也可以使代码进一步解耦,增加其重用性。

云函数有什么优势?

1. 简单易用

1.1 减少组件开销

使用云函数时,用户只需编写最重要的 “核心代码”,负载均衡、自动伸缩、网关等周边组件由平台负责,极大地降低了服务架构搭建的复杂性。

1.2 自动扩缩容

无需任何手动配置,云函数即可根据请求量自动横向扩缩。不管您的应用每天只有几个请求(如日志统计等定期事务),还是每秒有几千上万个请求(如移动应用的后端),云函数均可自动安排合理的计算资源满足业务需求。

2. 高效又创造性地开发

2.1 加速开发

云函数不要求特定框架或依赖(小程序云函数运行在 Node.js 环境中。我们可以如在 Node.js 环境中使用 JavaScript 一样在云函数中进行网络请求等操作。),开发者可以专注于核心代码的开发。同时开发人员可以组成多个小团队,单个模块的开发无需了解其他团队的代码细节。独立开发和迭代的速度变得前所未有的快,帮助用户把握住产品上线的黄金时间。

2.2 复用第三方服务

您可以使用云函数编写一些目的单一、逻辑独立的业务模块,因而可以完全复用已经成熟的第三方代码实现,例如,使用 npm 的 OAuth 实现登录模块。

2.3 简化运维

每个函数都是单独运行、单独部署、单独伸缩的,用户上传代码后即可自动部署,免除单体式应用部署升级难的问题。

3. 稳定可靠

3.1 高可用部署

云函数可以自动在每个地域中随机地选择可用区来运行。如果某个可用区因灾害或电力故障等导致瘫痪,云函数会自动地选择其他可用区的基础设施来运行,免除单可用区运行的故障风险。

3.2 与其他计算服务相辅相成

常驻的工作负载可以通过云服务器 CVM ,容器服务 TKE 来承载,而由事件触发的工作负载可以使用云函数。不同云服务满足不同的业务场景和业务需求,使得您的服务架构更加健壮。

4. 简化管理

4.1 简化安全配置

用户不再需要对 OS 入侵、登录风险、文件系统安全、网络安全和端口监听做复杂的配置和管理,一切交由平台处理,平台通过定制化的容器保证每个用户的隔离性。

4.2 可视化管理

用户可直接在控制台管理函数代码及函数何时运行(即函数触发器),无需复杂的配置文件即可一键部署和测试函数

5. 大幅度降低开销

5.1 永远不为空闲时间付费

函数在未执行时不产生任何费用,对一些并非常驻的业务进程来说开销将大大降低。函数执行时按请求数和计算资源的运行时间收费,价格优势明显,对初创期的开发者十分友好。

云函数的开发&发布

开通云开发、创建环境

在使用云开发能力之前需要先开通云开发。在开发者工具工具栏左侧,点击 “云开发” 按钮即可打开云控制台、根据提示开通云开发、创建云环境。默认配额下可以创建两个环境,各个环境相互隔离,每个环境都包含独立的数据库实例、存储空间、云函数配置等资源。每个环境都有唯一的环境 ID 标识,初始创建的环境自动成为默认环境。

指定云函数根目录、创建云函数

在项目根目录的 project.config.json 文件,新增 cloudfunctionRoot 字段,指定云函数的本地根目录:

  1. {
  2. "cloudfunctionRoot": "cloudfunctions/"
  3. }

接着,我们在(微信开发者工具-编辑器)云函数根目录上右键,在右键菜单中,可以选择 【新建Node.js 云函数】,我们将该云函数命名为 test。开发者工具在本地创建出云函数目录,我们可以看到类似如下的一个目录结构:

  1. -- cloudfunctions
  2. |---- test
  3. | |-- index.js
  4. | |-- config.json
  5. | |-- package.json

index.js是当前云函数的主入口,类似如下的一个云函数模版:

  1. // 云函数入口文件
  2. const cloud = require('wx-server-sdk')
  3. cloud.init()
  4. // 云函数入口函数
  5. exports.main = async (event, context) => {
  6. const wxContext = cloud.getWXContext()
  7. return {
  8. sum: event.a + event.b,
  9. openid: wxContext.OPENID,
  10. appid: wxContext.APPID,
  11. unionid: wxContext.UNIONID,
  12. }
  13. }

云函数的传入参数有两个,一个是 event 对象,一个是 context 对象。

  • event 指的是触发云函数的事件,当小程序端调用云函数时,event 就是小程序端调用云函数时传入的参数,外加后端自动注入的小程序用户的 openid 和小程序的 appid。
  • context 对象包含了此处调用的调用信息和运行状态,可以用它来了解服务运行的情况。

模版中所 requirewx-server-sdk 是一个帮助我们在云函数中操作数据库、存储以及调用其他云函数的微信提供的库。

接下来我就可以以 main函数为入口编写我们的业务逻辑。云函数在云端是直接运行在 Node.js(本文发布时的Node.js 版本是 10.15)中的,所以原生支持 async, await 等新规范中的 JS 语法。需要我们注意的是,每一个云函数是一个独立的项目,云函数在云端运行的时候是以一个独立的项目运行的。因此,我们在开发中不能引用函数目录外文件资源,当前函数所依赖的npm包也必须在当前目录中 npm install

config.json 是云函数的一些配置信息,用于配置 云接口权限和定时触发器 等配置信息。如下:

我们要在云端调用获取小程序码的接口,则需要在 config.json 中配置接口权限:

  1. // config.josn
  2. {
  3. "permissions": {
  4. "openapi": [
  5. "wxacode.getUnlimited"
  6. ]
  7. }
  8. }
  1. // index.js
  2. const cloud = require('wx-server-sdk')
  3. cloud.init()
  4. exports.main = async (event, context) => {
  5. try {
  6. const result = await cloud.openapi.wxacode.getUnlimited({
  7. scene: 'a=1'
  8. })
  9. return result
  10. } catch (err) {
  11. return err
  12. }
  13. }

本地调试

云开发提供了云函数本地调试功能,在本地提供了一套与线上一致的 Node.js 云函数运行环境,提供了 JS常见的单步调试/断点调试。

在微信开发者工具对应函数根目录上,右键选择【开启云函数本地调试】即可。

在本地调试界面中点击相应云函数并勾选【开启本地调试】方可进行该云函数的本地调试。取消勾选【开启本地调试】后可关闭对该云函数的本地调试。开启本地调试后,微信开发者工具模拟器中的对该云函数的请求、以及其他开启了本地调试的云函数的对该云函数的请求,都会自动请求到该本地云函数实例。

Tips: 若云函数中有使用使用到 npm 模块,需在云函数本地目录npm install后才可以开启本地调试。

云函数调用

在小程序中调用云函数:

  1. // callback 风格
  2. wx.cloud.callFunction({
  3. // 云函数名称
  4. name: 'add',
  5. // 传给云函数的参数
  6. data: {
  7. a: 1,
  8. b: 2,
  9. },
  10. success: function(res) {
  11. console.log(res.result.sum) // 3
  12. },
  13. fail: console.error
  14. })
  15. // promise风格
  16. wx.cloud.callFunction({
  17. // 云函数名称
  18. name: 'add',
  19. // 传给云函数的参数
  20. data: {
  21. a: 1,
  22. b: 2,
  23. },
  24. })
  25. .then(res => {
  26. console.log(res.result) // 3
  27. })
  28. .catch(console.error)

云函数调用云函数:

  1. const cloud = require('wx-server-sdk')
  2. cloud.init({
  3. env: cloud.DYNAMIC_CURRENT_ENV
  4. })
  5. exports.main = async (event, context) => {
  6. const res = await cloud.callFunction({
  7. // 要调用的云函数名称
  8. name: 'add',
  9. // 传递给云函数的参数
  10. data: {
  11. x: 1,
  12. y: 2,
  13. }
  14. })
  15. // 3
  16. return res.result
  17. }

部署及版本

部署

云函数的部署其实很简单,在需要部署的云函数的跟目录上右键选择 【创建并部署:所有文件】或者 【创建并部署:云端安装依赖(不上传node_modules)】即可。

需要特别注意的是,在部署云函数的时候一定要确认我们当前部署的【环境】,千万避免把测试环境的代码部署到线上环境!!!!

  • 关于环境
    小程序云函数默认可拥有最多两个环境,一个环境对应一整套独立的云开发资源,包括数据库、存储空间、云函数等资源。 在实际开发中,建议每一个正式环境(release)都搭配一个测试环境(test)

右键 云函数的根目录 可切换环境

右键 云函数的根目录 可切换环境

云函数部署

云函数部署

版本管理及灰度

云开发提供发布版本(快照)和多版本间调整流量比例的能力。我们可以借此能力实现灰度发布。

云函数版本
  • 一个云函数可以发布多个版本,一个版本就是一个函数在当前时刻的快照,包含其代码和配置(超时时间、环境变量等)。
  • 云函数始终存在一个 LATEST 版,即最新版。编辑器中上传云函数和在控制台更改配置始终更改 LATEST 版本。

要进行灰度发布,只需更改版本之前的流量配比,即可实现灰度。

创建版本,灰度发布

创建版本,灰度发布

日志及监控

监控

在云开发控制台的【监控图表】可以查看云函数的调用次数、运行时间、错误次数。

日志

小程序云开发的日志服务包含【日志】和【高级日志】两种。

  • 日志: 在这里可以查看云函数的调用日志,方便开发者对开发调试。云函数的脚本错误等异常信息,以及我们console.log()可以在这里查询。

  • 高级日志:提供了日志采集和检索分析等功能,方便开发者通过日志快速的发现和定位问题。每条日志可最长存储30天,超过 30 天的日志将被自动清理。

我们可以通过 wx-server-sdk提供的 logger() 方法主动上报高级日志。

  1. 通过 logger() 方法取得 log 对象
  2. 调用 log 对象上的 log / info / warn / error (对应不同 level 的日志等级)方法,传入一个对象作为参数,每调用一次会产生一条日志记录
  3. 对象的每一个对都会成为日志一条记录中的一个可检索的键值对,其中 value 不论值是什么都会被转成字符串。

如下:

  1. // 云函数入口文件
  2. const cloud = require('wx-server-sdk')
  3. cloud.init({
  4. env: cloud.DYNAMIC_CURRENT_ENV,
  5. })
  6. // 云函数入口函数
  7. exports.main = async (event, context) => {
  8. const wxContext = cloud.getWXContext()
  9. const log = cloud.logger()
  10. log.info({
  11. name: 'xx',
  12. cost: 10,
  13. attributes: {
  14. width: 100,
  15. height: 200,
  16. },
  17. colors: ['red', 'blue'],
  18. })
  19. // 输出到日志记录中会有这么一条记录:
  20. // {
  21. // "level": "info",
  22. // "name": "xx",
  23. // "cost": "10",
  24. // "attributes": "{ width: 100, height: 200 }",
  25. // "colors": "[ "red", "blue" ]"
  26. // ..., // 其他系统字段
  27. // }
  28. return {
  29. event,
  30. }
  31. }

告警设置

目前小程序·云开发提供两种告警配置:

  • 基础告警:包括资源使用量提醒和计费相关信息,告警规则由系统配置,开发者可修改对应的告警渠道。
  • 自定义告警:由开发者自定义告警条件。目前提供了 云函数错误次数和云函数运行时间 两个告警指标。

开发者可以通过微信开发者工具,在 【云开发控制台】 的 【设置】 页面中的 【告警设置】 中使用该功能。

更多信息参考 官方文档

一些问题

云函数有着自己独特的优势,但是它同样有着让人不容忽视的一些问题:

不适合长时间运行应用

由于云函数的计费是根据运行时间运行内存计费的,如果你的应用需要一直长期不间断的运行、处理大量的请求,那么你可能就不适合采用云函数。

冷启动时间

云函数在请求到来时才运行。这意味着,当应用不运行的时候就会进入 “休眠状态”,下次当请求来临时,应用将会需要一个启动时间,即冷启动

AWS Lambda 的冷启动时间

AWS Lambda 的冷启动时间

函数之间无法共享信息

每一个云函数都是一个独立的项目,每一次运行都是独立运行的,因此云函数的之间信息共享异常困难。

复杂业务/逻辑不好实现

复杂业务场景下我们可能要拆分很多的函数,如何决定函数的粒度,并且评估,实现和测试?如何管理和维护多个函数之间的关系?如何关联管理?

总结

经过我们线上的一段时间的实践,小程序云函数的整体运行还是非常可靠的。可以利用云函数做一些特定的业务封装,减少对后端的依赖扩展我们前端的开发边界。

写于 2020年10月13日小程序 4834

如非特别注明,文章皆为原创。

转载请注明出处: https://www.liayal.com/article/5f8591fd7ff0f07e0ea449bd

记小栈小程序上线啦~搜索【记小栈】【点击扫码】体验

你不想说点啥么?
😀😃😄😁😆😅😂🤣☺️😊😇🙂🙃😉😌😍😘😗😙😚😋😜😝😛🤑🤗🤓😎🤡🤠😏😒😞😔😟😕🙁☹️😣😖😫😩😤😠😡😶😐😑😯😦😧😮😲😵😳😱😨😰😢😥🤤😭😓😪😴🙄🤔🤥😬🤐🤢🤧😷🤒🤕😈👿👹👺💩👻💀☠️👽👾🤖🎃😺😸😹😻😼😽🙀😿😾👐👐🏻👐🏼👐🏽👐🏾👐🏿🙌🙌🏻🙌🏼🙌🏽🙌🏾🙌🏿👏👏🏻👏🏼👏🏽👏🏾👏🏿🙏🙏🏻🙏🏼🙏🏽🙏🏾🙏🏿🤝👍👍🏻👍🏼👍🏽👍🏾👍🏿👎👎🏻👎🏼👎🏽👎🏾👎🏿👊👊🏻👊🏼👊🏽👊🏾👊🏿✊🏻✊🏼✊🏽✊🏾✊🏿

评论

~ 评论还没有,沙发可以有 O(∩_∩)O~