Firebase云功能非常慢
我们正在使用新的Firebase云功能的应用程序上工作。当前正在发生的事情是将事务放入队列节点中。然后函数删除该节点并将其放入正确的节点。由于能够脱机工作,因此已经实现了该功能。
我们当前的问题是功能的速度。该函数本身大约需要400毫秒,所以没关系。但是有时该功能需要很长时间(大约8秒),而该条目已被添加到队列中。
我们怀疑服务器需要花费一些时间来启动,因为在第一个操作之后,我们再次执行该操作。它花费的时间更少。
有什么办法可以解决此问题?在这里,我添加了我们函数的代码。我们怀疑它没有问题,但是为了以防万一,我们添加了它。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const database = admin.database();
exports.insertTransaction = functions.database
.ref('/userPlacePromotionTransactionsQueue/{userKey}/{placeKey}/{promotionKey}/{transactionKey}')
.onWrite(event => {
if (event.data.val() == null) return null;
// get keys
const userKey = event.params.userKey;
const placeKey = event.params.placeKey;
const promotionKey = event.params.promotionKey;
const transactionKey = event.params.transactionKey;
// init update object
const data = {};
// get the transaction
const transaction = event.data.val();
// transfer transaction
saveTransaction(data, transaction, userKey, placeKey, promotionKey, transactionKey);
// remove from queue
data[`/userPlacePromotionTransactionsQueue/${userKey}/${placeKey}/${promotionKey}/${transactionKey}`] = null;
// fetch promotion
database.ref(`promotions/${promotionKey}`).once('value', (snapshot) => {
// Check if the promotion exists.
if (!snapshot.exists()) {
return null;
}
const promotion = snapshot.val();
// fetch the current stamp count
database.ref(`userPromotionStampCount/${userKey}/${promotionKey}`).once('value', (snapshot) => {
let currentStampCount = 0;
if (snapshot.exists()) currentStampCount = parseInt(snapshot.val());
data[`userPromotionStampCount/${userKey}/${promotionKey}`] = currentStampCount + transaction.amount;
// determines if there are new full cards
const currentFullcards = Math.floor(currentStampCount > 0 ? currentStampCount / promotion.stamps : 0);
const newStamps = currentStampCount + transaction.amount;
const newFullcards = Math.floor(newStamps / promotion.stamps);
if (newFullcards > currentFullcards) {
for (let i = 0; i < (newFullcards - currentFullcards); i++) {
const cardTransaction = {
action: "pending",
promotion_id: promotionKey,
user_id: userKey,
amount: 0,
type: "stamp",
date: transaction.date,
is_reversed: false
};
saveTransaction(data, cardTransaction, userKey, placeKey, promotionKey);
const completedPromotion = {
promotion_id: promotionKey,
user_id: userKey,
has_used: false,
date: admin.database.ServerValue.TIMESTAMP
};
const promotionPushKey = database
.ref()
.child(`userPlaceCompletedPromotions/${userKey}/${placeKey}`)
.push()
.key;
data[`userPlaceCompletedPromotions/${userKey}/${placeKey}/${promotionPushKey}`] = completedPromotion;
data[`userCompletedPromotions/${userKey}/${promotionPushKey}`] = completedPromotion;
}
}
return database.ref().update(data);
}, (error) => {
// Log to the console if an error happened.
console.log('The read failed: ' + error.code);
return null;
});
}, (error) => {
// Log to the console if an error happened.
console.log('The read failed: ' + error.code);
return null;
});
});
function saveTransaction(data, transaction, userKey, placeKey, promotionKey, transactionKey) {
if (!transactionKey) {
transactionKey = database.ref('transactions').push().key;
}
data[`transactions/${transactionKey}`] = transaction;
data[`placeTransactions/${placeKey}/${transactionKey}`] = transaction;
data[`userPlacePromotionTransactions/${userKey}/${placeKey}/${promotionKey}/${transactionKey}`] = transaction;
}
回答如下:这里的消防队员
听起来您正在经历所谓的函数冷启动。
[一段时间未执行函数时,Cloud Functions会将其置于使用较少资源的模式下。然后,当您再次点击该功能时,它将从该模式恢复环境。恢复所需的时间包括固定成本(例如,还原容器)和部分可变成本(例如,如果您使用大量节点模块,则可能需要更长的时间)。
我们将持续监控这些操作的性能,以确保开发人员体验和资源使用之间的最佳结合。因此,期望这些时间会随着时间的推移而改善。
好消息是,您仅应在开发过程中体会到这一点。一旦您的功能在生产中被频繁触发,它们几乎就不会再冷启动了。]