Serverless 学习 03 TodoList API 接口案例

TodoList API 接口案例

前面将云函数与 Express 进行了整合,下面通过一个 TodoList 接口案例继续学习云函数的使用开发,这个案例具备最基础的增删改查等功能。

添加业务路由

修改 app.js 将 TodoList 的业务处理分发到不同的路由请求:

// nihao\functions\node-app\app.js
const express = require('express')
const app = express()

app.use(express.json())
app.use(express.urlencoded({extended: true}))

const indexRouter = require('./router/index')
const todoRouter = require('./router/todo')

app.use('/', indexRouter)
app.use('/todo', todoRouter)

// app.use('/users', (req, res) => {
//   res.send('users again')
// })

module.exports = app

配置路由:

// nihao\functions\node-app\router\index.js
const express = require('express')
const router = express.Router()

router.get('/', (req, res) => {
  res.send('index router')
})

module.exports = router

// nihao\functions\node-app\router\todo.js
const express = require('express')
const router = express.Router()

// 获取任务
router.get('/', (req, res) => {
  res.send('get todo router')
})

// 添加任务
router.post('/', (req, res) => {
  res.send('post todo router')
})

// 修改任务
router.put('/', (req, res) => {
  res.send('put todo router')
})

// 删除任务
router.delete('/', (req, res) => {
  res.send('delete todo router')
})

module.exports = router

# 本地启动 Express,测试路由
nodemon www.js
# 部署到线上,进行测试
tcb fn code update node-app

可以使用 postman 进行本地及云函数的测试。

连接云数据库

根据 TodoList 的业务逻辑,首先肯定是先添加数据,才能进行增删改查。CloudBase 提供了云数据库,可以用来存储我们添加的数据,官方手册

在使用云数据库之前,需要先理清它的一个基本概念:

  • 腾讯云给我们提供的云数据库是一种文档型数据库,提供基础读写、聚合搜索、数据库事务、实时推送等功能;
  • 数据库中有数据库实例(Database)、集合(Collection)、记录(Record)着三个基本概念;
  • 每个云开发环境下有且只有一个数据库实例;
  • 数据库实例中,可以创建多个集合,可以将集合理解为一个文本文件,每个文件中可以存放多个类似 JSON 格式的对象,这样的对象被称为记录

在这里插入图片描述

创建集合

在这里插入图片描述
在这里插入图片描述

添加记录

点击集合名称进入文档列表,控制台是以“添加文档”的名义添加记录的:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意:_id 是云数据库自己管理的唯一标识,添加数据的 API 默认返回它(字段名 id),可以直接使用。也可以自定义一个 id 字段作为数据的唯一标识,但添加文档时必须填入值。

安装服务端 SDK

通过服务端调用,需要安装 server node.js SDK。

# 在 node-app 目录下安装 SDK
npm i @cloudbase/node-sdk@2.9.0

**注意:**官方说的是使用 npm i @cloudbase/node-sdk 直接安装,但是本例安装时报错 No matching version found for @cloudbase/node-sdk@latest.,打开 @cloudbase/node-sdk - npm (npmjs.com) 查看发布的版本,发现 latest 是 2.9.1 版本(仅7日下载量0),怀疑这个版本有什么问题,所以可以手动指定下载量较高的最新版本(当前 2.9.0)。

服务端调用

官方服务端调用参考示例

通过服务端调用,需要在 SDK 初始化参数中填入腾讯云密钥(SecretID 和 SecretKey),以及 env(环境 id,官方手册上的示例并没有说)

在这里插入图片描述

密码入口在右上角账户头像-访问管理,然后进入访问密钥-API密钥管理页面,点击新建密钥即可新建一条密钥:

在这里插入图片描述
在这里插入图片描述

注意:每一个账户可能会有多个密钥,通过密钥就可以在不登录账户的情况下访问腾讯云的几乎所有内容,甚至删除,所以建议在不使用的时候将密钥禁用。或者参考《访问管理 安全最佳实践》使用子账号进行相关资源操作。

// nihao\functions\node-app\router\todo.js
const express = require('express')
const router = express.Router()

const nodesdk = require('@cloudbase/node-sdk')

// 初始化 SDK
const app = nodesdk.init({
  env: 'mycloudes-xxx',
  secretId: 'xxx',
  secretKey: 'xxx'
})

const db = app.database()

// 获取任务
router.get('/', async (req, res) => {
  // 获取 todo 集合中的全部数据
  const backdb = await db.collection('todo').get()
  res.send(backdb)
})

...

nodemon www.js 启动本地服务,访问 http://localhost:3000/todo,发现控制台报错:

 Environment create in ap-guangzhou cannot access in ap-shanghai

因为 SDK 默认使用上海地域,所以无法访问广州地区创建的环境。

可以在初始化的时候通过 region 指定地域,详情参考 API 文档

// 初始化 SDK
const app = nodesdk.init({
  env: 'mycloudes-xxx',
  secretId: 'xxx',
  secretKey: 'xxx'
  region: 'ap-guangzhou'
})

再次访问 http://localhost:3000/todo,页面正常显示数据:

{
    "data": [
        {
            "_id": "5016c938628eef3e0044c42e4691c2e6",
            "content": "",
            "done": false,
            "title": ""
        }
    ],
    "requestId": "180fe5c9e12_2"
}
  • data:当前请求获取到的数据
  • requestId:当前请求的 id,每次请求都不一样

完成增删改接口

关于时区:云函数中的时区默认是 UTC+0,在函数中获取本地时间会和北京时间有 8 个小时的差异,所以建议自己管理数据的时间,参考手册-深入理解云函数-时区

// nihao\functions\node-app\router\todo.js
const express = require('express')
const router = express.Router()

const nodesdk = require('@cloudbase/node-sdk')

// 初始化 SDK
const app = nodesdk.init({
  env: 'mycloudes-xxx',
  secretId: 'xxx',
  secretKey: 'xxx'
  region: 'ap-guangzhou'
})

const db = app.database()

// 获取任务
router.get('/', async (req, res) => {
  // 获取 todo 集合中的全部数据
  const backdb = await db.collection('todo').get()
  res.send(backdb)
})

// 添加任务
router.post('/', async (req, res) => {
  // 校验参数
  if (req.body.title === undefined) {
    return res.send('缺少 title')
  }
  const todo = {
    title: req.body.title,
    createTime: Date.now(),
    done: false
  }

  const backdata = await db.collection('todo').add(todo)

  res.send(backdata)
})

// 修改任务
router.put('/', async (req, res) => {
  if (req.query._id === undefined) {
    return res.send('缺少 _id')
  }
  if (req.body.title === undefined) {
    return res.send('缺少 title')
  }
  if (req.body.done === undefined) {
    return res.send('缺少 done')
  }
  // 不能修改 _id 的值
  const todo = {
    title: req.body.title,
    done: req.body.done
  }
  const backdata = await db.collection('todo').doc(req.query._id).update(todo)
  res.send(backdata)
})

// 删除任务
router.delete('/', async (req, res) => {
  if (req.query._id === undefined) {
    return res.send('缺少 _id')
  }
  const backdata = await db.collection('todo').doc(req.query._id).remove()
  res.send(backdata)
})

module.exports = router

本地测试完成后就可以部署到线上使用了。

总结

本例,我们在应用中创建了一个云函数,并将云函数与 Express 进行整合,配合云数据库写好了增删改查的 API,现在我们可以在任意客户端请求接口开发业务。

但是,这样的开发方式并不是 Serverless 的最佳使用方式。

在我们的代码中,是将整个后端应用的全部业务能力,写进了一个云函数中,这样做的好处就是方便管理,毕竟在一个应用下只有一个云函数。

但是单个云函数的并发是有限的,并行的函数实例个数由云厂商决定,超过限制后,事件队列就需要等待其它函数实例执行完毕后,再生成新的函数实例。

可是,之前不是说 Serverless 是弹性伸缩,会根据业务处理的需求自动调配资源,为什么还会有函数的并发限制呢?

要搞清楚这一点,就需要了解 FaaS 的运行机制

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值