由 firebase 实时数据库中的写入触发的云功能中的多个连接和巨大的下载开销

multiple connections and huge download overhead in cloud function trigged by writes in firebase realtime database

我在位置 /test/{folder}

中编写了由写入触发的以下云函数 writetest

函数 writetest 只是在位置 /register/{folder} 中写入函数被触发的(近似)时间。

我们可以在 html 文件下面看到 testfirebase.html(我删除了我的项目的信息)。当您在浏览器中加载此 html 时,首先登录该应用程序,然后单击“上传”按钮,在 100 个不同位置 /test/0、/test/1 上传 1KB 数据 100 次, /test/2, ...,/test/99.

当然这会触发云函数writetest 100次。我的问题是,这还会在项目控制台的使用选项卡中生成超过 80 个连接,特别是在项目控制台的“使用”选项卡中,您可以看到大约 440KB 的下载数据。对我来说,完全有下载数据是令人惊讶的,下载数据比上传数据大很多倍更令人惊讶。也许这与每个连接中的 3.5Kb“握手”有关?由于我的真实应用程序经常进行这些上传,并且每次上传都非常小(~1KB),这会显着增加使用由写入触发的云函数的成本。这笔额外费用是不可避免的吗?

这是云函数的代码

exports.writetest = functions.database.ref(
    "/test/{folder}")
    .onWrite(async (snapshot, context)=> {
      return admin.database().ref("/register/"+
        context.params.folder).update(
          {
            "time": admin.database.ServerValue.TIMESTAMP});
    });

html 文件testfirebase.html(您必须使用有权写入 /test/ 的用户登录)

<html lang="en">
 
<head>
   
    <script src=
   "https://www.gstatic.com/firebasejs/8.7.0/firebase.js">
    </script>
    
    
    <script src="https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth.js"></script>
    <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth.css" />
    
     <script>
         
         const firebaseConfig = {
           apiKey: "XX",
           authDomain: "XX.firebaseapp.com",
           databaseURL: "https://XX-default-rtdb.firebaseio.com",
           projectId: "XX",
           storageBucket: "XX.appspot.com",
           messagingSenderId: "XX",
           appId: "XX",
           measurementId: "${config.measurementId}"
         };
         
         // Initialize Firebase
         firebase.initializeApp(firebaseConfig);
         
         
         var ui = new firebaseui.auth.AuthUI(firebase.auth());
         
         var dbase=firebase.database();
         
         
         
         const uiConfig = {
           callbacks: {
             signInSuccessWithAuthResult(authResult, redirectUrl) {
                 
               return true;
             },
             uiShown() {
             },
           },
           signInFlow: 'popup',
           signInSuccessUrl: 'https://mydomain.app/testfirebase.html',
           signInOptions: [
             firebase.auth.EmailAuthProvider.PROVIDER_ID,
             firebase.auth.GoogleAuthProvider.PROVIDER_ID,
           ],
         };


         firebase.auth().onAuthStateChanged( async (user) => {
           if (user) {
             console.log("user logged");
               
               console.log("user id:" +user.uid);
               
           } else {
               
               console.log("no user logged");
               ui.start('#firebaseui-auth-container', uiConfig);
           }
         });
         
         
         async function dbset(path,data)
         {
             
             return new Promise ((resolve,reject)=>{
                 
             
             var reference = dbase.ref(path);
             
             reference.set(data).then(()=>{resolve("OK"); console.log("OK");}).catch((error) => {
                 reject("ERROR DBSET:"+error);
               });
             });
             
         }
         
         async function upload()
         {
             
            var onekbytestring="";
            for (let k=0;k< 1000;k++) {onekbytestring = onekbytestring + "1";}
             
          for (let j=0; j< 100;j++)
          {
            dbset("test/"+j,{b:onekbytestring });
          }
          }
        
     </script>
     
     
     
     </head>
     <body>
    

    <div id="firebaseui-auth-container"></div>
         
      <div >
      
      <button  onclick="upload()">Upload</button>
      
      </div>
     
</body>
 
</html>

在路径上调用 update 不会path 下载数据。

但是由于您使用 Admin SDK,因此需要通过 HTTPS 建立到服务器的 Web 套接字连接,其中包括建立 TLS/SSL 连接的大约 4Kb 开销。

由于这些客户端连接,每一个也会算作一个连接。这些连接可能会在服务器上停留几分钟,同时等待套接字超时。如果发生这种情况,您还会在控制台中看到这些连接。


请注意,在真实的 use-case 中,连接可能会分散得更多。在这种情况下,我希望您会看到更多 re-use 已建立的连接,因为调用更有可能命中之前使用过的 Cloud Functions 实例,因此 SDK 可能仍具有已建立的连接连接。


可以尝试使用 REST API 发送更新,看看是否有任何不同。虽然这肯定会减少连接数(因为更新的 REST API 是无连接的),但我怀疑它会对数据大小产生很大影响。尽管如此,如果您担心这一点,还是值得一试。