云开发过程中遇到过多次云函数自动重复调用问题,每隔10秒重复调用共9次,百思不得其解。后与售后技术人员沟通了解,云函数不支持异步操作,并有多种内部限制因素,最终都会导致触发云函数自动重试机制,导致云函数重复调用。
触发云函数重试几个因素如下:
1.云函数执行耗时代码,超过云函数运行时限会被认为超时,触发云函数自动重试。建议将耗时代码拆解分发给其他云函数多批次执行,非小程序调用云函数超时最长可以设置900s。
2.云函数执行结束后没有return,超过云函数运行时限会被认为超时,触发云函数自动重试。云函数最后一定要return,return前建议延时1秒,防止残余代码未完全执行结束而被中断return。
3.云函数不支持异步操作,云函数return后仍有异步代码持续执行,会被认为超时,触发云函数自动重试。通过new promise包裹+async/await将异步代码转为同步。
4.云函数代码报错导致触发云函数自动重试。云函数代码一定要包裹try catch。
5.回调函数和触发函数一定要在规定时间内return,超过时限会被认为超时,触发云函数自动重试。事件触发必须5s内return,微信云支付回调大概是3s左右。
6.尽量使用腾讯云web端进行测试,不要使用微信开发工具IDE云端测试,由于控制台缓存版本不好处理,可能会导致IDE云端测试触发重复调用。官方建议web端进行云端测试。
7.对于高并发易超时的负责业务逻辑,通过多级调用+延时调用云函数,降低每秒并发量和缩短代码执行耗时,减少云函数超时自动重试带来的数据重复、流量翻倍等问题同时缩小问题影响范围。
示例代码:
/**
* 使用 Promise 和 async/await 来实现线程睡眠的效果,需要在 Node.js 版本 7.6 或更高版本上运行。
* @param {*} ms 等待指定的毫秒数
*/
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* 函数内部异步代码按顺序同步执行
*/
async function does(){
try {
for (let i = 0; i < 3; i++) {
//异步代码同步执行
await new Promise((resolve,reject)=>{
setTimeout(() => {
let msg = '成功,第' + i + '个同步代码,等3s';
console.log(msg)
if(msg){
resolve(msg)
}else{
reject('失败')
}
}, 3000);
})
}
//耗时代码,通过分发给其他云函数执行,防止云函数超时报错,触发重试机制
cloud.callFunction({
// 云函数名称
name: 'test',
// 传给云函数的参数
data: {
},
})
} catch (error) {
console.error("出错了:" + error);
}
};
// 云函数入口函数
exports.main = async (event, context) => {
try { //包裹try catch防止云函数报错,触发重试机制
await does()
await sleep(1000); //延迟一秒结束,防止未完全执行结束而被立刻return
console.log('入口函数结束')
} catch (error) {
console.error("出错了:" + error);
}
return //一定要return,否则云函数认为没有执行结束导致超时报错,触发重试机制
}