Firebase云端功能非常慢 [英] Firebase cloud functions is very slow

查看:321
本文介绍了Firebase云端功能非常慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在研究一个使用新的firebase云功能的应用程序。目前发生的事情是一个事务放入队列节点。然后该函数删除该节点并将其放入正确的节点中。由于能够脱机工作,因此已经实施。

我们目前的问题是函数的速度。函数本身大约需要400ms,所以没关系。但有时这些函数需要很长时间(大约8秒),而条目已经被添加到队列中了。

我们怀疑服务器需要时间来启动,因为当我们在第一个之后再次执行操作时。这需要更少的时间。

有什么办法可以解决这个问题吗?在这里我添加了我们的功能的代码。

  const functions = require('firebase-functions' ); 
const admin = require('firebase-admin');
const database = admin.database();

exports.insertTransaction = functions.database $ b $ .ref('/ userPlacePromotionTransactionsQueue / {userKey} / {placeKey} / {promotionKey} / {transactionKey}')
.onWrite event => {
if(event.data.val()== null)return null;

//获取键
const userKey = event.params.userKey;
const placeKey = event.params.placeKey;
const promotionKey = event.params.promotionKey;
const transactionKey = event.params.transactionKey;

// init更新对象
const data = {};

//获取事务
const transaction = event.data.val();

//传递事务
saveTransaction(data,transaction,userKey,placeKey,promotionKey,transactionKey);
//从队列中移除
data [`/ userPlacePromotionTransactionsQueue / $ {userKey} / $ {placeKey} / $ {promotionKey} / $ {transactionKey}`] = null;

/ / fetch promotion
database.ref(`promotions / $ {promotionKey}`).once('value',(snapshot)=> {
//检查促销是否存在。
if(!snapshot.exists()){
return null;
}

const promotion = snapshot.val();
$ b $ //获取当前印数
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;

//确定是否有新的完整卡片
const currentFullcards = Math.floor(currentStampCount> 0?currentStampCount / promotion .stamps:0);
const newStamps = currentStampCount + transaction.amount; $ b $ const const newFullcards = Math.floor(newStamps / promotion.stamps);

if(newFullcards> (让我= 0;我<(newFullcards - currentFullcards); i ++){
常卡Transaction = {
action:pending,
promotion_id:promotionKey,
user_id:userKey,
金额:0,
类型:stamp,
date:transaction.date,
is_reversed:false
};

saveTransaction(data,cardTransaction,userKey,placeKey,promotionKey);
$ b $ const completionPromotion = {
promotion_id:promotionKey,
user_id:userKey,
has_used:false,
date:admin.database.ServerValue.TIMESTAMP
};
$ b常量promotionPushKey =数据库$ b $ .ref()
.child(`userPlaceCompletedPromotions / $ {userKey} / $ {placeKey}`)
.push()
.key;

data [`userPlaceCompletedPromotions / $ {userKey} / $ {placeKey} / $ {promotionPushKey}`] = completedPromotion;
data [`userCompletedPromotions / $ {userKey} / $ {promotionPushKey}`] = completedPromotion;



return database.ref()。update(data);
},(error)=> {
//如果发生错误,请登录到控制台。
console.log('The read failed:'+ error.code);
返回null;
});

},(error)=> {
//如果发生错误,请登录到控制台。
console.log('The read failed:'+ error.code);
返回null;
});
});
$ b $函数saveTransaction(data,transaction,userKey,placeKey,promotionKey,transactionKey){
if(!transactionKey){
transactionKey = database.ref('transactions')。push ()。键;
}

data [`transactions / $ {transactionKey}`] = transaction;
data [`placeTransactions / $ {placeKey} / $ {transactionKey}`] = transaction;
data [`userPlacePromotionTransactions / $ {userKey} / $ {placeKey} / $ {promotionKey} / $ {transactionKey}`] = transaction;


解决方案

firebaser here

这听起来像是你正在经历一个所谓的冷启动的功能。



当你的函数在一段时间内没有被执行的时候,云端函数会把它放在一个使用较少资源的模式中。然后当你再次点击该功能时,它将从这个模式恢复环境。恢复所需的时间包括固定成本(例如恢复容器)和部分变量成本(例如,如果使用大量节点模块,则可能需要更长时间)。

我们不断监视这些操作的性能,以确保开发人员体验与资源使用之间的最佳组合。所以期待这些时间会随着时间的推移而改善。

好​​消息是你只能在开发过程中体验到这一点。一旦你的功能在生产中频繁触发,他们很可能再也不会碰到寒冷的开始。

We're working on an application that uses the new firebase cloud functions. What currently is happening is that a transaction is put in the queue node. And then the function removes that node and puts it in the correct node. This has been implemented because of the ability to work offline.

Our current problem is the speed of the function. The function itself takes about 400ms, so that's alright. But sometimes the functions take a very long time (around 8 seconds), while the entry was already added to the queue.

We suspect that the server takes time to boot up, because when we do the action once more after the first. It takes way less time.

Is there any way to fix this problem? Down here i added the code of our function. We suspect there's nothing wrong with it, but we added it just in case.

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 here

It sounds like you're experiencing a so-called cold start of the function.

When your function hasn't been executed in some time, Cloud Functions puts it in a mode that uses fewer resources. Then when you hit the function again, it restores the environment from this mode. The time it takes to restore consists of a fixed cost (e.g. restore the container) and a part variable cost (e.g. if you use a lot of node modules, it may take longer).

We're continually monitoring the performance of these operations to ensure the best mix between developer experience and resource usage. So expect these times to improve over time.

The good news is that you should only experience this during development. Once your functions are being frequently triggered in production, chances are they'll hardly ever hit a cold start again.

这篇关于Firebase云端功能非常慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆