【问题标题】:Firestore in cloud function takes a few minutes to initialize and make first requests云功能中的 Firestore 需要几分钟来初始化并发出第一个请求
【发布时间】:2020-05-04 21:20:56
【问题描述】:

对于在 Cloud Function 上运行的这个简单的 Firestore 查询,如果我们有一段时间没有调用它并且需要创建一个新的客户端连接(最长的时间是 100 多秒),它总是需要很长时间

以下是最小可重现index.ts 和详细日志。我尝试同时使用admin.firestore()new Firestore({ grpc }) 并得到了类似的结果。

import {https, config} from 'firebase-functions';
import * as admin from "firebase-admin";
const { Firestore } = require('@google-cloud/firestore');
const grpc = require('@grpc/grpc-js');

let initialized = false;

exports.timeQuery = https.onRequest(async (req:any, res) => {
        res.json({received: true});

    if (!initialized) {
      admin.initializeApp(config().firebase);
      admin.firestore.setLogFunction(console.log);
      initialized = true;
    }
    // using gRPC
    console.log('using gRPC via @google-cloud/firestore')
    const db = new Firestore({ grpc });
    // using admin node SDK
    // const db = admin.firestore();

    await db.collection("debugCollection")
        .doc("debug")
        .get();
    }
  );

我在 Firestore 中启用了调试日志记录,发现初始化 Firestore GAPIC 客户端需要 47 秒。

Firestore (3.7.5) 2020-05-04T20:37:23.541Z ##### [Firestore]: Initialized Firestore GAPIC Client
  1:36:36.054 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:36:36.054Z peRnr [ClientPool.acquire]: Creating a new client

在发送请求和接收查询响应之间,又花了 35 秒。

Firestore (3.7.5) 2020-05-04T20:38:00.139Z peRnr [Firestore.requestStream]: Received response: {"transaction":{"type":"Buffer","data":[]},"readTime":{"seconds":"1588624676","nanos":86619000},"missing":"projects/xxxxxxxx-my-project-id/databases/(default)/documents/debugCollection/debug","result":"missing"}
  1:37:25.141 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:37:25.141Z peRnr [Firestore.requestStream]: Sending request: {"database":"projects/xxxxxxxx-my-project-id/databases/(default)","documents":["projects/xxxxxxxx-my-project-id/databases/(default)/documents/debugCollection/debug"]}

这里是详细日志。


  1:38:05.440 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:38:05.440Z peRnr [Firestore.getAll_]: Received 1 results
  1:38:05.240 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:38:05.240Z peRnr [Firestore._initializeStream]: Received stream end
  1:38:00.340 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:38:00.340Z peRnr [Firestore.getAll_]: Document missing: projects/xxxxxxxx-my-project-id/databases/(default)/documents/debugCollection/debug
  1:38:00.141 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:38:00.140Z peRnr [Firestore._initializeStream]: Releasing stream
  1:38:00.141 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:38:00.139Z peRnr [Firestore.requestStream]: Received response: {"transaction":{"type":"Buffer","data":[]},"readTime":{"seconds":"1588624676","nanos":86619000},"missing":"projects/lovecaster-staging/databases/(default)/documents/debugCollection/debug","result":"missing"}
  1:37:25.141 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:37:25.141Z peRnr [Firestore.requestStream]: Sending request: {"database":"projects/xxxxxxxx-my-project-id/databases/(default)","documents":["projects/xxxxxxxx-my-project-id/databases/(default)/documents/debugCollection/debug"]}
  1:37:25.140 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:37:25.140Z peRnr [ClientPool.acquire]: Re-using existing client with 100 remaining operations
  1:37:24.440 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:37:24.440Z ##### [Firestore.initializeIfNeeded]: Detected project ID: xxxxxxxxxxx-my-projectID
  1:37:23.541 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:37:23.541Z ##### [Firestore]: Initialized Firestore GAPIC Client
  1:36:36.054 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:36:36.054Z peRnr [ClientPool.acquire]: Creating a new client
  1:36:36.052 PM
  timeQuery
  Firestore (3.7.5) 2020-05-04T20:36:36.051Z ##### [Firestore]: Initialized Firestore
  1:36:36.050 PM
  timeQuery
  using gRPC via @google-cloud/firestore
  1:36:36.043 PM
  timeQuery
  Function execution took 54 ms, finished with status code: 200
  1:36:35.989 PM
  timeQuery
  Function execution started

和节点包版本: "firebase-admin": "^8.11.0", "@grpc/grpc-js": "0.8.1", "@google-cloud/firestore": "3.7.5",

【问题讨论】:

    标签: javascript node.js firebase google-cloud-firestore google-cloud-functions


    【解决方案1】:

    您的函数之所以如此,是因为您在所有工作完成之前发送响应。根据documentation,该函数在响应发送后立即终止。之后的任何其他工作都可能无法正确完成。因此,您对res.json({received: true}); 的调用应该是函数中的最后

    如果您希望您的函数立即向客户端发送响应,并在此之外继续工作,那么您将无法使用单个 HTTP 函数来执行此操作。相反,您将不得不将该工作卸载到另一个服务或功能。向pubsub function 发送消息以使其在第一个功能停止的后台继续运行是很常见的。

    【讨论】:

    • 谢谢道格!我们将 res.send() 移到最后,它解决了这个问题。
    • 很高兴听到这个消息。 Stack Overflow 的惯例是,如果答案有帮助,请投票并将其标记为正确 - 请使用此答案右侧的按钮。
    • 感谢您的提示。赞成(尽管可能因为我没有足够的声誉而没有显示)并接受了答案。
    猜你喜欢
    • 2021-04-14
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 2017-10-10
    相关资源
    最近更新 更多