node.js - Firebase 云功能很慢

标签 node.js firebase firebase-realtime-database google-cloud-functions

我们正在开发一个使用新的 firebase 云功能的应用程序。当前正在发生的事情是将事务放入队列 Node 中。然后该函数删除该 Node 并将其放入正确的 Node 中。由于能够离线工作,因此已经实现了这一点。

我们当前的问题是函数的速度。该函数本身大约需要 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;
}

最佳答案

firebaser 在这里

听起来您正在经历所谓的函数冷启动。

当您的函数在一段时间内未执行时,Cloud Functions 会将其置于使用较少资源的模式,这样您就无需为未使用的计算时间付费。然后,当您再次点击该功能时,它会从此模式恢复环境。恢复所需的时间由固定成本(例如恢复容器)和部分可变成本(例如 if you use a lot of node modules, it may take longer)组成。

我们会持续监控这些操作的性能,以确保在开发人员体验和资源使用之间实现最佳组合。因此,预计这些时间会随着时间的推移而改善。

好消息是您应该只在开发过程中体验到这一点。一旦你的函数在生产环境中被频繁触发,它们很可能几乎不会再次冷启动,特别是如果它们有稳定的流量。但是,如果某些功能倾向于看到流量高峰,您仍然会看到每个高峰的冷启动。在这种情况下,您可能需要考虑 minInstances setting始终保持一定数量的延迟关键函数实例温暖。

关于node.js - Firebase 云功能很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42726870/

相关文章:

javascript - 类型错误 : Cannot read property 'FieldValue' of undefined

ios - 如何获取当前用户图片并显示在imageView中?

ios - 使用自动增量 Swift 3 在 Firebase 数据库中存储帖子(图像、标题)

javascript - 使用服务器js中的key从mongo获取数据

firebase - 如何禁用 Cloud Firestore?

ios - 来自 Firebase 的数据未加载到数组中

android - getInstance() 不适用于实时数据库中除 us-central1 之外的其他位置

JSON.parse 返回对象对象

node.js - 了解 npm 的 "skippingAction Module is inside a symlinked module"

node.js - 非socket.io 进程的示例是什么?