收藏
回答

云函数连接redis后不关闭的话日志会总是报超时的错误。需要处理吗?在每个云函数里把redis连接关


/opt/utils/cache.js

const Redis = require('ioredis')
const redis = new Redis({
  host: "xxx",
  port: '6379',
  // family: 4,
  password: 'xxx',
  // db: 0
})
exports.redis = redis


// 云函数入口文件
const cloud = require('wx-server-sdk')


cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境
const TcbRouter = require('tcb-router')
const db = cloud.database()
const _ = db.command
const $ = db.command.aggregate


const cache = require('/opt/utils/cache.js') // 使用到了云函数的层管理
const dateUtil = require('/opt/utils/dateUtil.js') // 使用到了云函数的层管理


// 云函数入口函数
exports.main = async (event, context) => {


  const app = new TcbRouter({ event })
  // const { } = event
  const { OPENID, UNIONID } = cloud.getWXContext()
  const page = event.page ? Number(event.page) : 0;
  const pageSize = event.pageSize ? Number(event.pageSize) : 10;
  const skip = page * pageSize


  app.use(async (ctx, next) => {
    ctx.data = {}
    await next();
  });


  // 1.hot 热门问题(按回答人数)
  app.router('hot', async (ctx, next) => {
    try {
      const date = dateUtil.formatTime(new Date());//当前日期
      const cacheKey = `question:hot:${date}:${page}:${pageSize}`
      const cacheKeyExists = await cache.redis.exists(cacheKey)
      const cacheData = await cache.redis.lrange(cacheKey, 0, -1);


      if (cacheKeyExists) {
        if (cacheData.length == 1 && cacheData[0] == 'EMPTY') {
          // 缓存结果为空
          ctx.body = { code: 0, date, cacheKey, msg: '缓存结果空', data: [] }
        } else {
          // 有缓存
          let result = []
          for (let index = 0; index < cacheData.length; index++) {
            const element = JSON.parse(cacheData[index]);
            result.push(element)
          }
          ctx.body = { code: 0, date, cacheKey, msg: '缓存结果', data: result }
        }


      } else {
        // 从数据库查询数据
        const { data } = await db.collection('question').where({
          status: 'open',
          type: 'public'
        }).orderBy('total_answers', 'desc').skip(skip).limit(pageSize).field({
          create_time: 1,
          title: 1,
          total_answers: 1,
          total_viewers: 1,
          total_collectors: 1,
        }).get();


        if (data && data.length) {
          // 循环遍历存储到redis
          for (let index = 0; index < data.length; index++) {
            // 时间戳转日期
            data[index].create_time = dateUtil.toDate(data[index].create_time)
            const element = JSON.stringify(data[index]);
            await cache.redis.rpush(cacheKey, element);
            await cache.redis.expire(cacheKey, 60 * 60 * 24);//24小时过期
          }
        } else {
          // 数据为空时,设置缓存值为特殊字符串'EMPTY'
          await cache.redis.rpush(cacheKey, 'EMPTY', () => {
            cache.redis.expire(cacheKey, 60 * 60 * 24);//24小时过期
          })
        }

        ctx.body = { code: 0, date, cacheKey, msg: '数据库结果', data }
      }

    } catch (error) {
      ctx.body = { code: 1, msg: '获取热门问题失败', data: error }
    } finally {
      cache.redis.disconnect()
    }


  })
  // 2.latest 最新问题
  app.router('latest', async (ctx, next) => {
    try {
      const date = dateUtil.formatTime(new Date());//当前日期
      const cacheKey = `question:latest:${date}:${page}:${pageSize}`
      const cacheKeyExists = await cache.redis.exists(cacheKey)
      const cacheData = await cache.redis.lrange(cacheKey, 0, -1);


      if (cacheKeyExists) {
        if (cacheData.length == 1 && cacheData[0] == 'EMPTY') {
          // 缓存结果为空
          ctx.body = { code: 0, date, cacheKey, msg: '缓存结果空', data: [] }
        } else {
          // 有缓存
          let result = []
          for (let index = 0; index < cacheData.length; index++) {
            const element = JSON.parse(cacheData[index]);
            result.push(element)
          }
          ctx.body = { code: 0, date, cacheKey, msg: '缓存结果', data: result }
        }


      } else {
        // 从数据库查询数据
        const { data } = await db.collection('question').where({
          status: 'open',
          type: 'public'
        }).orderBy('create_time', 'desc').skip(skip).limit(pageSize).field({
          create_time: 1,
          title: 1,
          total_answers: 1,
          total_viewers: 1,
          total_collectors: 1,
        }).get();


        if (data && data.length) {
          // 循环遍历存储到redis
          for (let index = 0; index < data.length; index++) {
            // 时间戳转日期
            data[index].create_time = dateUtil.toDate(data[index].create_time)
            const element = JSON.stringify(data[index]);
            await cache.redis.rpush(cacheKey, element);
            await cache.redis.expire(cacheKey, 60 * 60 * 24);//24小时过期
          }
        } else {
          // 数据为空时,设置缓存值为特殊字符串'EMPTY'
          await cache.redis.rpush(cacheKey, 'EMPTY', () => {
            cache.redis.expire(cacheKey, 60 * 60 * 24);//24小时过期
          })
        }

        ctx.body = { code: 0, date, cacheKey, msg: '数据库结果', data }
      }

    } catch (error) {
      ctx.body = { code: 1, msg: '获取最新问题失败', data: error }
    } finally {
      cache.redis.disconnect()
    }
  })
 
  return app.serve();
}



如上图代码中,每个云函数中 调用cache.redis.disconnect()就能调用成功。

这样做的话会有性能上的影响吗?这样每次调用云函数都要重新连接redis吧?

还是有什么更好的办法忽略掉日志的错误吗?

回答关注问题邀请回答
收藏

2 个回答

  • showms
    showms
    2023-03-09

    我觉得在云函数上面使用redis,可能得结合他的运行机制,云函数是无状态的,运行的实例随时会被销毁,所以在上面连接redis,每次请求进来就需要重连一下redis,用完关闭,这样的做法是最稳妥的。

    https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/mechanism.html

    2023-03-09
    有用 1
    回复 5
    • momo
      momo
      发表于移动端
      2023-03-09
      还有一种常驻云函数又是咋回事?
      2023-03-09
      回复
    • showms
      showms
      2023-03-09回复momo
      就是系统不会回收云函数的实例,你们现在用的哪种
      2023-03-09
      回复
    • momo
      momo
      发表于移动端
      2023-03-09回复showms
      就普通的云函数。这常驻云函数的话是不是就不需要关闭redis连接了?可以保持redis常连?
      2023-03-09
      回复
    • showms
      showms
      2023-03-09回复momo
      可以试一下,不过也要考虑一下常驻的费用
      2023-03-09
      回复
    • momo
      momo
      发表于移动端
      2023-03-09回复showms
      是的。常驻要费用。并发不高的情况下没必要。
      2023-03-09
      回复
  • Mr.Zhao
    Mr.Zhao
    2023-03-08

    用完就关闭,要不然持续计费到超时时间

    2023-03-08
    有用 1
    回复 3
    • momo
      momo
      发表于移动端
      2023-03-09
      每次请求重连redis,再关闭?这样会影响速度吗?
      2023-03-09
      回复
    • Mr.Zhao
      Mr.Zhao
      2023-03-09回复momo
      项目要精确到纳秒吗
      2023-03-09
      回复
    • momo
      momo
      发表于移动端
      2023-03-09回复Mr.Zhao
      不需要
      2023-03-09
      回复
登录 后发表内容