2017-03-10 33 views
42

Chúng tôi đang làm việc trên một ứng dụng sử dụng các chức năng đám mây firebase mới. Những gì hiện đang xảy ra là một giao dịch được đặt trong nút xếp hàng. Và sau đó chức năng loại bỏ nút đó và đặt nó vào nút chính xác. Điều này đã được triển khai vì khả năng làm việc ngoại tuyến.Chức năng đám mây của Firebase rất chậm

Vấn đề hiện tại của chúng tôi là tốc độ của hàm. Chức năng chính nó mất khoảng 400ms, vì vậy đó là alright. Nhưng đôi khi các chức năng mất một thời gian rất dài (khoảng 8 giây), trong khi mục nhập đã được thêm vào hàng đợi.

Chúng tôi nghi ngờ rằng máy chủ cần thời gian để khởi động, bởi vì khi chúng tôi thực hiện hành động một lần nữa sau lần đầu tiên. Nó mất ít thời gian hơn.

Có cách nào để khắc phục sự cố này không? Ở đây tôi thêm mã của chức năng của chúng tôi. Chúng tôi nghi ngờ không có gì sai với nó, nhưng chúng tôi đã thêm nó chỉ trong trường hợp.

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; 
} 
+0

Có an toàn khi không trả lại Lời hứa của các cuộc gọi trên một lần() 'trên không? – jazzgil

Trả lời

46

firebaser đây

Có vẻ như bạn đang gặp phải một sự khởi đầu cái gọi là lạnh của hàm.

Khi chức năng của bạn chưa được thực thi trong một khoảng thời gian, Chức năng đám mây sẽ đặt nó ở chế độ sử dụng ít tài nguyên hơn. Sau đó, khi bạn nhấn lại chức năng, nó sẽ khôi phục môi trường từ chế độ này. Thời gian cần để khôi phục bao gồm chi phí cố định (ví dụ: khôi phục vùng chứa) và chi phí biến một phần (ví dụ: nếu bạn sử dụng nhiều mô đun nút, có thể mất nhiều thời gian hơn).

Chúng tôi liên tục theo dõi hiệu suất của các hoạt động này để đảm bảo sự kết hợp tốt nhất giữa trải nghiệm của nhà phát triển và mức sử dụng tài nguyên. Vì vậy, mong đợi những thời gian này để cải thiện theo thời gian.

Tin vui là bạn chỉ nên trải nghiệm điều này trong quá trình phát triển. Một khi chức năng của bạn đang được kích hoạt thường xuyên trong sản xuất, rất có thể họ sẽ hầu như không bao giờ đánh một khởi đầu lạnh nữa.

+8

Tôi hiện đang gặp sự cố tương tự. Đôi khi phải mất 8 ~ 15 giây trước khi hàm được thực hiện. Ngay cả khi chức năng này được thực hiện lần cuối như 5 phút trước. Điều này sẽ được cải thiện? – Brianvdb

+1

@Frank Việc gửi yêu cầu giả là một ý tưởng hay để giữ cho các chức năng còn sống? Nếu vậy, bạn khuyên bạn nên thực hiện thường xuyên như thế nào? (Sản xuất của chúng tôi không đủ phổ biến để tránh những sự chậm trễ này) –

+0

@PatrixWilliams Nếu bạn gặp phải sự cố 8-15 giây sau 5m, tôi sẽ quét nhật ký của bạn để đảm bảo rằng bạn không nhận được bất kỳ loại ngoại lệ chưa xử lý nào yêu cầu chúng tôi cung cấp cho bạn một ví dụ mới (và do đó một khởi đầu lạnh mới). –

8

Cập nhật - trông giống như rất nhiều những vấn đề này có thể được giải quyết bằng cách sử dụng biến ẩn process.env.FUNCTION_NAME như đã thấy ở đây: https://github.com/firebase/functions-samples/issues/170#issuecomment-323375462

này sẽ cho phép cho một giải pháp gọn gàng hơn nhiều so với những gì tôi đã làm dưới đây (mặc dù giải thích dưới đây vẫn giữ).


Dường như yêu cầu tệp và khởi tạo chung xảy ra trong phạm vi toàn cầu là nguyên nhân lớn làm chậm trong khi khởi động nguội.

Là một dự án được nhiều chức năng phạm vi toàn cầu đang bị ô nhiễm ngày càng nhiều làm cho vấn đề tồi tệ hơn -. Đặc biệt là nếu bạn phạm vi chức năng của mình thành các file riêng biệt (chẳng hạn như bằng cách sử dụng Object.assign(exports, require('./more-functions.js')); trong index.js bạn

tôi đã quản lý để đạt được những lợi ích to lớn trong hiệu suất khởi động nguội bằng cách di chuyển tất cả các yêu cầu của tôi vào một phương thức init như dưới đây và sau đó gọi nó là dòng đầu tiên bên trong bất kỳ định nghĩa chức năng nào cho tệp đó. từ khoảng 7-8s xuống 2-3s khi áp dụng kỹ thuật này cho một projec t với ~ 30 chức năng trên 8 tệp. Điều này cũng có vẻ gây ra các chức năng cần được khởi động lạnh ít thường xuyên hơn (có lẽ do sử dụng bộ nhớ thấp hơn?)

Thật không may điều này vẫn làm cho các chức năng HTTP hầu như không thể sử dụng cho việc sử dụng sản xuất của người dùng.

Hy vọng nhóm Firebase có một số kế hoạch trong tương lai để cho phép phạm vi chức năng phù hợp để chỉ các mô-đun liên quan cần được tải cho từng chức năng.

0

Tôi cũng đã làm những việc này, giúp cải thiện hiệu suất khi các chức năng được làm nóng lên, nhưng khởi đầu lạnh lẽo đang giết chết tôi. Một trong những vấn đề khác tôi gặp phải là với cors, bởi vì phải mất hai chuyến đi đến các chức năng đám mây để hoàn thành công việc. Tôi chắc rằng tôi có thể sửa chữa điều đó.

Khi bạn có ứng dụng trong giai đoạn đầu (demo) khi nó không được sử dụng thường xuyên, hiệu suất sẽ không tuyệt vời. Đây là một cái gì đó mà cần được xem xét, như sớm chấp nhận với sản phẩm đầu cần phải nhìn tốt nhất của họ ở phía trước của khách hàng tiềm năng/nhà đầu tư. Chúng tôi yêu thích công nghệ này vì vậy chúng tôi đã di chuyển từ các khung công tác cũ và đã cố gắng, nhưng ứng dụng của chúng tôi có vẻ khá chậm chạp vào thời điểm này. Tôi sẽ tiếp tục thử một số chiến lược khởi động để làm cho nó trông đẹp hơn

0

Một vấn đề khác là kế hoạch miễn phí (Spark).

spark

Khi tôi chuyển sang kế hoạch trả (Blaze trong trường hợp của tôi), sau đó chức năng của tôi bắt đầu làm việc nhanh.

blaze

Các vấn đề liên quan