【问题标题】:Google cloud datastore: multiple save calls only creating one entity谷歌云数据存储:多次保存调用只创建一个实体
【发布时间】:2020-07-03 15:39:02
【问题描述】:

我有一个带有 http 触发器的谷歌云功能,我想用它来将信息保存到数据存储中。

当我向它发送信息时,第一个请求将起作用并在数据存储中创建一个实体,但后续请求不会。

这是我的功能:


const Datastore = require('@google-cloud/datastore')
const datastore = new Datastore({
    projectId: 'XXXX'
})
const myKey = datastore.key({namespace: 'mynamespace', path: ['mypath']})

exports.metrics = async (req, res) => {
    let type = req.body.type
    let user = req.body.user
    let date = req.body.date || new Date().toISOString()

    await datastore
        .upsert({
            key: myKey,
            data: {
                type,
                user,
                date
            }
        })
        .then(response => {
            res.status(200).send(response)

        })
        .catch(err => {
            res.status(400).send(err)
        })

}

我没有收到错误。我总是得到 200 响应,但响应各不相同。 对于有效的请求,mutationResults 包含有关密钥的信息。在那些不起作用的请求中,mutationResults 键为空。

那么为什么只有一些请求有效?

【问题讨论】:

    标签: node.js google-cloud-datastore


    【解决方案1】:

    你的代码对我有用...

    需要注意的是:对单个(数据存储)实体的更新曾经被限制为 5/秒(!?),但这似乎已经放宽|改进但仍然有限:

    https://cloud.google.com/datastore/docs/best-practices#updates_to_an_entity

    我假设您使用的是“Datastore”(不是“Firestore Native”)模式,因为您使用的是命名空间;代码不会出错,但在 Native 模式下不起作用。

    注意如果您要部署为云函数,则在新建 Datastore 时无需提供具有 project 值的对象,因为该值由环境提供。

    注意要记住的另一件事是,因为 key每个 实例的全局常量,您将能够生成多个实体如果您扩展到 >1 个 Cloud Functions 实例

    /* jshint esversion: 10 */
    /* globals exports,require */
    
    const { Datastore } = require("@google-cloud/datastore");
    const datastore = new Datastore();
    
    const key = datastore.key({
        namespace: "ns",
        path: ["path"]
    });
    console.log(`${key}`);
    
    exports.metrics = async (req, res) => {
        let type = req.body.type;
        let user = req.body.user;
        let date = req.body.date || new Date().toISOString();
    
        await datastore.upsert({
            key: key,
            data: {
                type,
                user,
                date
            }
        }).then(response => {
            res.status(200).send(response);
        }).catch(err => {
            res.status(400).send(err);
        });
    };
    

    package.json:

    {
        "name": "62718657",
        "version": "0.0.1",
        "dependencies": {
            "@google-cloud/datastore": "6.0.0"
        }
    }
    

    和:

    gcloud functions deploy metrics \
    --allow-unauthenticated \
    --entry-point=metrics \
    --trigger-http \
    --project=${PROJECT} \
    --region=us-central1 \
    --runtime=nodejs10
    

    Functions|upsert 成功时,我(似乎只)得到 200 秒。

    我可以强制 upsert 争用:

    ENDPOINT=$(\
      gcloud functions describe metrics \
      --project=${PROJECT} \
      --format="value(httpsTrigger.url)")
    
    for t in {1..100}
    do
      printf "%s\n" $(curl --silent ${ENDPOINT})
    done
    

    生成:

    {
      "code":10,
      "details":"too much contention on these datastore entities. please try again.",
      "metadata":{
        "internalRepr":{},
        "options":{}
      }
    }
    

    和:

    gcloud functions logs read --project=${PROJECT}
    LEVEL  NAME     EXECUTION_ID  TIME_UTC                 LOG
           metrics  gn3g6prcri96  2020-07-07 17:38:08.736  undefined
           metrics  ogcineo00ryu  2020-07-07 17:38:08.743  failure: Error: 10 ABORTED: too much contention on these datastore entities. please try again.
           metrics  ogcineo00ryu  2020-07-07 17:38:08.743  undefined
    D      metrics  ogcineo00ryu  2020-07-07 17:38:08.745  Function execution took 8083 ms, finished with status code: 400
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-05
      • 2015-07-17
      相关资源
      最近更新 更多