Google Cloud Datastore:导出与特定查询匹配的实体

时间:2019-01-16 15:43:56

标签: python google-cloud-datastore google-cloud-functions

背景

我需要向大约100万台设备发送大量通知,并且正在使用Google Cloud Functions进行构建。

在当前设置中,我将每个设备令牌作为PubSub消息排队:

  • 在DataStore中存储待处理的通知,用于跟踪重试和成功状态
  • 尝试发送通知
  • 将通知标记为成功或失败(如果已重试且未通过)

此过程由人工上载带有所有令牌的CSV文件手动启动。原则上,内置重试应该足够,但是我想确保,如果云功能本身或APNs / FCM出现问题,我可以返回上载格式相同的所有失败令牌的CSV,因此如果用户认为这是个好主意,则用户只能重试失败的问题。

我将通知作为作业的一部分运行,该作业用于与通知状态一起进行查询。为此,我在job_idstatus上设置了复合索引,并对所有匹配的通知运行查询,并希望将其作为文件流传输给用户或存储在其中Google Cloud Storage,以便用户可以从那里下载。

问题

假设接近总通知数量的操作失败,并且我想将所有令牌存储在一个文件中,那么我的第一个实现就是遍历所有匹配项并构建结果。问题是,以这种方式检索它们时,每100_000个条目大约需要1分钟。对于接近所有通知的操作,它将使我超出Cloud Function的最大超时时间。每个实体共约300个字节,这使得整个导出量约为300MB。通过添加更大的索引,我可以将其减小到大约一半/三分之二。

我唯一想到的替代方法是将通知分片​​以将整个组分成100个分片,创建100个文件(每个通知包含10k个通知),然后全部下载并在用户尝试下载文件时将它们缝合在一起。

我发布问题的原因是,这感觉像是一个相对简单的问题,并且此解决方案感觉比我预期的要复杂一些,因此我认为我可能会遗漏一些东西。

问题

  • 我是否缺少一种显而易见的,更轻松的方法来实现自己想要的目标?
  • 是否只是按照预期的方式进行类似处理,我应该接受复杂性吗?

代码

为清楚起见,这是我正在运行的代码段,我只是迭代返回的响应以产生输出。

    def get_failures(job_id):
        query = client.query(kind = Notification.kind)
        query.add_filter('job_id', '=', str(job_id))
        query.add_filter('status', '=', "failure")
        return query.fetch()

1 个答案:

答案 0 :(得分:1)

针对此问题的可靠解决方案是使用Google Dataflow。目前,我正使用它来执行此操作,从而在Google Cloud Storage中生成csv文件,其中包含与给定的数据存储区查询匹配的所有〜500k记录。

但是,要进行设置可能有点麻烦。

在进行此操作之前,我使用了Google Task Queue,它具有10分钟的超时而不是30秒的超时。我不确定您是否可以仅在云函数中执行此操作,还是不确定是否需要启动一个简单的App Engine项目来充当这些任务的请求处理程序