如何在分布式环境中处理文件路径

时间:2016-03-29 23:50:02

标签: celery filepath distributed-computing

我正在设置分布式芹菜环境以对PDF文件进行OCR。我有大约3M PDF和OCR是CPU绑定的,所以我们的想法是创建一个服务器集群来处理OCR。

在我编写任务时,我有这样的事情:

@app.task
def do_ocr(pk, file_path):
    content = run_tesseract_command(file_path)
    item = Document.objects.get(pk=pk)
    item.content = ocr_content
    item.save()

问题我有什么最好的方法是让file_path在分布式环境中工作。人们通常如何处理这个问题?现在我的所有文件都只是存放在我们其中一台服务器上的一个简单目录中。

3 个答案:

答案 0 :(得分:5)

如果您在linux环境中,最简单的方法是使用sshfs在群集中的/mnt文件夹foreach节点中安装远程文件系统。然后,您可以将节点名称传递给do_ocr函数,并且所有数据都是当前节点的本地数据 例如,您的群集有N个节点,名为:node1,...,nodeN
让我们配置node1,foreach节点挂载远程文件系统。这是node1的/ etc / fstab文件的示例

sshfs#user@node2:/var/your/app/pdfs    /mnt/node2 fuse    port=<port>,defaults,user,noauto,uid=1000,gid=1000        0       0
....
sshfs#user@nodeN:/var/your/app/pdfs    /mnt/nodeN fuse    port=<port>,defaults,user,noauto,uid=1000,gid=1000        0       0

在当前节点(node1)中创建一个名为当前服务器的符号链接,指向pdf的路径

ln -s /var/your/app/pdfs node1

您的mnt文件夹应包含远程文件系统和符号链接

user@node1:/mnt$ ls -lsa
0 lrwxrwxrwx  1 user user      16 apr 12  2016 node1 -> /var/your/app/pdfs
0 lrwxrwxrwx  1 user user      16 apr 12  2016 node2
...
0 lrwxrwxrwx  1 user user      16 apr 12  2016 nodeN

然后你的功能应该是这样的:

import os
MOUNT_POINT = '/mtn'
@app.task
def do_ocr(pk, node_name, file_path):
    content = run_tesseract_command(os.path.join(MOUNT_POINT,node_name,file_path))
    item = Document.objects.get(pk=pk)
    item.content = ocr_content
    item.save()

它的工作方式就像当前机器中的所有文件一样,但是远程逻辑可以透明地为您工作

答案 1 :(得分:2)

嗯,有多种方法可以处理它,但让我们坚持使用最简单的方法之一:

  • 由于您想使用多台服务器处理大量文件,我的第一个建议是在每台服务器上使用相同的操作系统,因此您不必担心跨平台兼容性
  • 使用'cluster'这个词表示所有这些服务器应该知道它们的共同状态 - 它增加了复杂性,试图切换到无国籍工人的农场(通过'无国籍'我的意思是“不知道其他服务器”,因为他们应该至少知道他们自己的状态,例如:IDLE,IN_PROGRESS,QUEUE_FULL或更多(如果需要))
  • 对于文件列表处理部分,您可以使用pull或push模型:
    • 推送模型可以通过一个简单的应用程序轻松实现,该应用程序可以抓取文件并将它们(例如:通过SCP,FTP等)发送到一组可用的服务器;服务器可以监视其本地目录以进行更改并获取要处理的新文件;它也非常容易扩展 - 只需启动更多服务器并更新推送客户端(即使在运行时);唯一的限制是推送客户的表现
    • 拉模型有点棘手,因为你必须处理更多的复杂性;拥有一组服务器意味着每个节点具有适当的起始索引和偏移 - 它将使错误处理更加困难,加上它不容易扩展(想象添加两次作为更多的服务器来加速处理和更新每个节点上的索引和偏移..似乎是一个容易出错的解决方案)
  • 我认为网络流量并不是一个大问题 - 要处理的3M文件会在某个地方生成它,无论如何......
  • 收集/存储结果是一个不同的球场,但这里可能的解决方案列表是无限的

答案 2 :(得分:1)

由于我错过了很多您的架构详细信息和您的应用程序细节,因此您可以将此答案作为指导性答案而非严格的答案。 您可以按以下顺序采用此方法:

1-部署内部文件服务器,将所有文件存储在一个位置并提供服务

示例:

  

http://interanal-ip-address/storage/filenameA.pdf

     

http://interanal-ip-address/storage/filenameB.pdf

     

http://interanal-ip-address/storage/filenameC.pdf

依旧......

2-安装/部署Redis

3-创建一个上传客户端/服务/流程,它将获取您要上传的文件并将其传递到上述存储位置(/storage/),以便您的文件在上传后可用,同时将完整文件路径URL推送到预定义的Redis列表/队列(构建在链接列表数据结构上),如下所示:http://internal-ip-address/storage/filenameA.pdf

您可以在Redis Lists下方获取有关LPUSH和RPOP的详细信息:http://redis.io/topics/data-types-intro

示例:

  1. 文件上传表单,将文件直接存储到存储区域
  2. 文件上传实用程序/命令行/后台进程,您可以自己创建它或使用一些现有工具将文件上传到存储位置,从特定位置获取文件,无论是网址还是某些文件其他具有您文件的服务器
  3. 4-现在我们来到您的芹菜工作者,您的每个工作人员应从Redis队列中提取(RPOP)其中一个文件URL,从内部文件服务器下载文件(我们在第一步中构建),并且按照您希望的方式进行所需的处理。

    Redis文档中需要注意的一件重要事项:

      

    列表具有使其适合实现的特殊功能   队列,通常作为进程间的构建块   通信系统:阻塞操作。

         

    然而,有时列表可能是空的并且有   无需处理,因此RPOP只返回NULL。在这种情况下是消费者   被迫等待一段时间并再次使用RPOP重试。这就是所谓的   轮询,在这种情况下不是一个好主意,因为它有几个   缺点

         

    因此Redis实现了名为BRPOP和BLPOP的命令,这些命令是版本   如果列表为空,RPOP和LPOP能够阻止它们:它们将返回   只有当一个新元素被添加到列表中时,或者当一个元素被添加到调用者时   达到用户指定的超时。

    如果能回答你的问题,请告诉我。

    要记住的事情

    • 您可以根据需要添加任意数量的工作人员,因为此解决方案非常实用 可扩展,你唯一的瓶颈是Redis服务器,你可以在停电或服务器崩溃时建立集群并保持队列

    • 您可以使用RabbitMQ,Beanstalk,Kafka或任何其他排队/消息系统替换redis,但由于简单性和开箱即用的无数功能,Redis已经在本次竞赛中获得提名。