如何处理GAE上的大文件处理?

时间:2016-12-07 10:27:54

标签: python algorithm google-app-engine google-cloud-datastore app-engine-ndb

我正在寻找一种强大而快速的方法来处理Google App Engine中的大型文件处理。

它的工作原理如下(最后的简化工作流程):

  1. 客户发送CSV文件,我们的服务器将逐行处理。
  2. 上传文件后,NDB数据存储Uploads中会添加一个条目,其中包含CSV名称,文件路径(到Google存储)以及一些基本信息。然后,创建一个任务,称为"预处理"。
  3. 预处理任务将循环遍历CSV文件的所有行(可能是数百万),并为每行添加一个NDB条目到UploadEntries模型,其中包含CSV ID,行,如果此行已开始处理,则结束处理(" is_treating"," is_done")
  4. 要提取/处理的数据和一些指示符(布尔值)
  5. 一旦预处理任务结束,它就会将信息更新到客户端" XXX行将被处理"
  6. 拨打Uploads.next()next方法将:
    • 搜索UploadEntriesis_treating的{​​{1}},
    • 将在Redis数据存储区中为找到的下一行添加任务。 (使用Redis数据存储区是因为此处的工作是在不受Google管理的服务器上进行的)
    • 还将在任务is_done中创建一个新条目(此任务在5分钟后运行并检查7)已正确执行。如果没有,它认为Redis / Outside服务器发生故障并且与7)相同,没有结果("错误"相反)。)
    • 然后,它会为该条目将Process-healthcheck更新为True。
  7. 外部服务器将处理数据,并通过向服务器上的端点发出POST请求来返回结果。
  8. 该端点更新数据存储区中的UploadEntries.is_treating条目(包括" UploadEntries"和" is_treating"),并致电{ {1}}开始下一行。
  9. 在Uploads.next中,当搜索下一个条目时什么都不返回时,我认为最终会处理该文件,并调用将使用已处理数据重建CSV的任务is_done,并将其返回到顾客。
  10. 这里有一些要记住的事情:

    1. 执行实际工作的服务器不在Google AppEngine之内,这就是我不得不想出Redis的原因。
    2. 当前的处理方式使我可以灵活处理要处理的并行条目数:在5)中,Uploads.next()方法包含一个post-process参数,可以让我搜索{{1并行处理。可以是1,5,20,50。
    3. 我不能直接将Uploads.next()任务中的所有行添加到Redis,因为在这种情况下,下一个客户将不得不等待第一个文件完成处理,这将堆积花了太长时间
    4. 但是这个系统有各种各样的问题,这就是为什么我转向你的帮助:

      1. 有时,此系统速度太快,数据存储区尚未正确更新,并且在调用limit时,返回的条目已在处理中(仅n尚未处理)推送到数据库)
      2. Redis或我的服务器(我真的不知道)有时会松开任务,或者在没有进行处理后发出POST请求,因此任务永远不会进入pre-processing。这就是我必须实施Healcheck系统的原因,以确保无论如何都能正确对待生产线。这有一个双重优势:该任务的名称包含csv ID和行。使每个文件唯一。如果我的数据存储区不是最新的并且同一个任务运行两次,那么运行状况检查的创建将失败,因为已存在相同的名称,让我知道存在并发问题,所以我忽略了该任务,因为它意味着数据存储尚未更新。
      3. 我首先考虑在一个独立的进程中逐行运行该文件,但这有一个很大的缺点,就是无法并行运行多行。此外,Google将专用目标的运行限制为24小时(非默认值),当文件非常大时,可以运行超过24小时。

        有关信息,如果有帮助,我使用 Python

        为简化工作流程,以下是我尝试以最佳方式实现的目标:

        • 处理一个大文件,运行多个并行处理,每行一个。
        • 使用Redis将工作发送到外部服务器。完成后,外部服务器通过POST请求将结果返回给主服务器
        • 主服务器然后更新有关该行的信息,并转到下一行

        如果有人有更好的方法,我真的很感激。我真的相信我不是第一个做这种工作的人,而且我很确定我做得不好。

        (我相信Stackoverflow是Stack Exchange发布这类问题的最佳部分,因为它是一个算法问题,但它也有可能我没有看到更好的网络如果是的话,我很抱歉。

1 个答案:

答案 0 :(得分:1)

  

执行实际工作的服务器不在Google AppEngine

之内

您是否考虑过使用Google Cloud Dataflow来处理大型文件? 它是一个托管服务,将为您处理文件拆分和处理。

基于最初的想法,这是一个大纲过程:

  • 用户使用signed urls或blobstore API
  • 将文件直接上传到Google云端存储
  • 来自AppEngine的请求启动一个小型计算引擎实例,该实例启动阻止请求(BlockingDataflowPipelineRunner)以启动数据流任务。 (我担心它需要是一个计算实例,因为沙箱和阻塞I / O问题)。
  • 当数据流任务完成时,计算引擎实例将被解除阻止并将消息发布到pubsub。
  • pubsub消息调用AppEngine服务上的webhook,将任务状态从“进行中”更改为“完成”,以便用户可以获取其结果。