使用Firebase Cloud Functions更新Firestore文档极慢问题求助
我正在尝试通过Firebase Cloud Functions更新Firestore文档,由于更新无需考虑现有值、以单文档更新为主且冲突风险极低,所以没使用事务。但现在单条测试用例耗时约3分钟,作为初级开发者从没遇到过这么严重的延迟,找不到问题原因。
完整代码
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.authenticator = functions.region('asia-northeast1').https.onRequest(async (req, res) => { const startTime = new Date().getTime(); console.log("Function execution started at: ", new Date().toISOString()); if (req.method !== "POST") { console.log("Method Not Allowed"); return res.status(405).send("Method Not Allowed"); } const data = req.body; if (!data || !data.data || !Array.isArray(data.data)) { console.log("Bad Request"); return res.status(400).send("Bad Request"); } res.status(200).send("Processing..."); console.log("Process started at: ", new Date().toISOString()); for (const item of data.data) { if (!item || !item.phoneNum || !item.authCode) { console.log("Invalid data: ", item); continue; } try { const updateStart = new Date().getTime(); console.log("Update started for authCode: ", item.authCode, " at: ", new Date().toISOString()); await admin.firestore().collection("auth").doc(item.authCode).update({ phoneNum: item.phoneNum, verified: true, timestamp: admin.firestore.FieldValue.serverTimestamp() }); const updateEnd = new Date().getTime(); console.log("Success: ", item.authCode, " at: ", new Date().toISOString(), " Update took: ", (updateEnd - updateStart) / 1000, " seconds"); } catch (err) { console.error(`Error processing ${item.authCode}:`, err); } } const endTime = new Date().getTime(); console.log("Process ended at: ", new Date().toISOString()); console.log("Total execution time: ", (endTime - startTime) / 1000, " seconds"); });
运行日志
Function execution started Function execution started at: 2024-07-09T21:28:39.167Z
Process started at: 2024-07-09T21:28:39.188Z
Update started for authCode: 519504f79458497cb8c4709739fbc877 at: 2024-07-09T21:28:39.188Z
Function execution took 80 ms, finished with status code: 200
Success: 519504f79458497cb8c4709739fbc877 at: 2024-07-09T21:31:36.657Z
Update took: 177.469 seconds
Process ended at: 2024-07-09T21:31:36.957Z
Total execution time: 177.79 seconds
环境信息
- Cloud Functions区域:
asia-northeast1 - Firestore区域:
asia-northeast3 - 请求来源:Google Apps Scripts经Gmail处理后的POST请求
- 此前在
us-central1区域处理更新速度正常
1. 核心问题:函数提前终止导致延迟
从日志能看到,函数在发送200响应后就标记为执行完成(耗时80ms),但后续的Firestore更新还在后台运行。Cloud Functions对于已完成响应的函数,会进入闲置状态,资源被回收或优先级降低,导致后续异步操作被严重延迟。
你在代码里先调用res.status(200).send("Processing..."),再执行异步更新,这是关键错误。HTTP函数必须在所有异步操作完成后再发送响应,否则函数会被强制进入闲置,后续操作变慢甚至失败。
2. 修复代码
把发送响应的逻辑移到所有更新操作完成之后:
// 移除原来的res.status(200).send("Processing..."); // ... // 所有循环完成后再发送响应 res.status(200).send("Processing completed"); console.log("Process ended at: ", new Date().toISOString()); console.log("Total execution time: ", (endTime - startTime) / 1000, " seconds");
3. 区域不匹配的影响
Cloud Functions和Firestore不在同一区域(asia-northeast1 vs asia-northeast3),跨区域调用会增加延迟,但不会达到3分钟这么夸张。如果条件允许,最好把两者调整到同一区域,进一步降低网络耗时。
4. 批量更新优化(可选)
如果后续需要处理多条数据,可以用Promise.all并行执行更新,提升效率:
const updatePromises = []; for (const item of data.data) { if (!item || !item.phoneNum || !item.authCode) { console.log("Invalid data: ", item); continue; } updatePromises.push( admin.firestore().collection("auth").doc(item.authCode).update({ phoneNum: item.phoneNum, verified: true, timestamp: admin.firestore.FieldValue.serverTimestamp() }) .then(() => { console.log("Success: ", item.authCode); }) .catch(err => { console.error(`Error processing ${item.authCode}:`, err); }) ); } await Promise.all(updatePromises);
内容的提问来源于stack exchange,提问作者한경완

