AppScript异步函数因用户过多执行失败,求解决方案
解决方案
问题分析
你的代码存在几个关键问题,直接导致高并发场景下执行失败:
- 冗余的async/await:SpreadsheetApp的所有API都是同步执行的,用await不仅没用,还可能干扰锁的逻辑执行。
- 过长的锁等待超时:
lock.waitLock(20000000)设置了约5.5小时的等待时间,但AppScript单脚本最长执行时间仅6分钟,后续请求会因超时直接失败。 - 无锁释放保障:如果
appendRow执行出错,锁不会被主动释放,会导致后续请求永远拿不到锁,形成死锁。 - 无容错机制:没有处理锁获取失败的情况,请求会一直阻塞到超时,没有给用户反馈。
修正后的代码
function submitForm(time, caseID, inputScreeshot, projectID, workflow, language, policy) { const id = "someid"; const sheet = SpreadsheetApp.openById(id).getSheetByName('data'); const email = Session.getActiveUser().getEmail(); const timestamp = new Date(); const lock = LockService.getScriptLock(); try { // 设置30秒超时,超过则直接返回失败提示 if (!lock.tryLock(30000)) { throw new Error("当前提交请求过多,请稍后重试"); } sheet.appendRow([timestamp, time, caseID, inputScreeshot, projectID, workflow, language, policy, email]); } catch (e) { // 可选:将错误记录到日志表,方便排查问题 const logSheet = SpreadsheetApp.openById(id).getSheetByName('error_log'); if (logSheet) { logSheet.appendRow([new Date(), e.message]); } throw e; // 抛出错误让前端提示用户 } finally { // 无论成功失败,确保锁被释放 if (lock.hasLock()) { lock.releaseLock(); } } }
额外优化建议
- 减少服务调用次数:尽量复用sheet对象,避免重复调用
openById和getSheetByName。 - 批量写入优化:如果前端支持积累多条数据再提交,改用
getRange批量写入,能大幅提升效率并缩短锁的持有时间。 - 前端限流:在页面添加防抖逻辑,限制同一用户短时间内重复提交,降低后端压力。
- 查看执行日志:在Google Apps脚本编辑器的「查看」→「执行日志」中查看具体错误信息,针对性排查问题。
内容的提问来源于stack exchange,提问作者Samuel Lino
相关产品推荐
相关产品推荐

