Python 如何使用Django文件存储在API和Worker之间共享文件 目标

Python 如何使用Django文件存储在API和Worker之间共享文件 目标,python,django,api,docker,worker,Python,Django,Api,Docker,Worker,我想构建一个本地docker compose部署,这样我就有5个服务 雷迪斯 博士后 兔子 Django API Django工人 在此部署中,用户通过API端点上传文件。此端点将文件存储在模型中的FileField字段中 在单独的事务中,用户将通过单独的端点触发异步任务。此任务将负责 下载文件 提取文件 启动子任务以执行中间处理步骤 将处理结果上载到数据库 中间处理步骤不应将任何文件上载到数据库 中间处理步骤是使用django的内部文件存储解决方案在那里下载和上载文件。这是通过与此问题

我想构建一个本地docker compose部署,这样我就有5个服务

  • 雷迪斯
  • 博士后
  • 兔子
  • Django API
  • Django工人
在此部署中,用户通过API端点上传文件。此端点将文件存储在模型中的
FileField
字段中

在单独的事务中,用户将通过单独的端点触发异步任务。此任务将负责

  • 下载文件
  • 提取文件
  • 启动子任务以执行中间处理步骤
  • 将处理结果上载到数据库
中间处理步骤不应将任何文件上载到数据库

中间处理步骤是使用django的内部文件存储解决方案在那里下载和上载文件。这是通过与此问题无关的文件系统层次结构实现的

问题 我已设法使本地文件系统使用此配置。如果我运行
redis
postgres
rabbitmq
的后端。然后,我在本地机器上运行API和Worker,一切正常

当我创建一个
docker时,编写
配置并将所有内容解耦。手术似乎中断了。在我的docker compose日志中,我看到了:

worker_1  | [2019-10-23 22:27:34,626: WARNING/ForkPoolWorker-2] //--------------------------------------------------------------------------------
worker_1  | [2019-10-23 22:27:34,627: WARNING/ForkPoolWorker-2] // BEGINNING TASK
worker_1  | [2019-10-23 22:27:34,627: WARNING/ForkPoolWorker-2] //--------------------------------------------------------------------------------
worker_1  | [2019-10-23 22:27:34,628: WARNING/ForkPoolWorker-2] // Root Job - 183916ca-f6e6-4e7c-a997-e8f516ccf8be
worker_1  | [2019-10-23 22:27:34,628: WARNING/ForkPoolWorker-2] // Parent Job - None
worker_1  | [2019-10-23 22:27:34,628: WARNING/ForkPoolWorker-2] // Current Job - 183916ca-f6e6-4e7c-a997-e8f516ccf8be
worker_1  | [2019-10-23 22:27:34,628: WARNING/ForkPoolWorker-2] //--------------------------------------------------------------------------------
worker_1  | [2019-10-23 22:27:34,629: WARNING/ForkPoolWorker-2] // PERFORMING DATA SET PRE PROCESSING
worker_1  | [2019-10-23 22:27:34,629: WARNING/ForkPoolWorker-2] //--------------------------------------------------------------------------------
worker_1  | [2019-10-23 22:27:34,629: WARNING/ForkPoolWorker-2] {'data_set_id': 1, 'starting_node': 'Live', 'organization_id': 1}
worker_1  | [2019-10-23 22:27:34,630: WARNING/ForkPoolWorker-2] Downloading the files required to run!
worker_1  | [2019-10-23 22:27:34,645: WARNING/ForkPoolWorker-2] Downloading remote file `organizations/1/data_sets/flow_cytometry/triple_hello_world_payload.tgz`
worker_1  | [2019-10-23 22:27:34,646: WARNING/ForkPoolWorker-2] Exists: `False`
worker_1  | [2019-10-23 22:27:34,646: WARNING/ForkPoolWorker-2] ERROR occured: [Errno 2] No such file or directory: '/opt/api_webserver/media/organizations/1/data_sets/flow_cytometry/triple_hello_world_payload.tgz'.
worker_1  | [2019-10-23 22:27:34,653: INFO/ForkPoolWorker-2] Task api.versions.v1.tasks.main_task.main_task[183916ca-f6e6-4e7c-a997-e8f516ccf8be] succeeded in 0.02647909999359399s: {'iteration': 0, 'completion': 0, 'status': 'ERROR', 'message': 'Excecuting `main_task` failed!', 'error': 'Error in `main_task`: [Errno 2] No such file or directory: \'/opt/api_webserver/media/organizations/1/data_sets/flow_cytometry/triple_hello_world_payload.tgz\'.'}
如果我进入
worker
docker容器
并检查文件系统,则
媒体
目录和文件的路径不存在。
如果我进入
api
docker容器
并检查文件系统,
媒体
目录和文件的路径确实存在

相关代码 我不会提供视图代码或api代码,因为api工作正常

上传和文件检索在
workers
过程中通过使用
django
default\u storage
界面进行处理

这个问题与worker有关,下面是一些相关代码

worker.py
#Python标准库
导入操作系统
#第三方图书馆
导入临时文件
#习俗
从models.data\u set\u模型导入数据集
从tasks.helpers导入下载远程文件
def下载数据集(数据集id):
打印(“下载运行所需的文件!”)
data\u set=DataSet.objects.get(id=data\u set\u id)
远程文件路径=数据集文件名
远程\u文件\u名称=os.path.basename(远程\u文件\u路径)
临时目录路径=tempfile.mkdtemp()
临时压缩文件路径=os.path.join(临时目录路径、远程文件名)
下载远程文件(远程文件路径、临时压缩文件路径)
返回临时压缩文件路径
helpers.py
#Python标准库
#不适用
#第三方图书馆
从django.core.files.storage导入默认存储
#自定义库
#不适用
def下载远程文件(远程文件路径、本地文件路径):
打印(f“下载远程文件”{remote\u file\u path}`)
打印(f“Exists:`{default\u storage.Exists(remote\u file\u path)}`)
远程文件内容=无
使用默认\u存储。打开(远程\u文件\u路径)作为远程\u文件\u句柄:
打印(“读取文件内容”)
remote\u file\u contents=remote\u file\u handle.read()
打印(f“将远程文件内容放入`{local\u file\u path}`”)
打开(本地文件路径,“wb”)作为本地文件句柄:
本地文件句柄写入(远程文件内容)
悬而未决的问题
  • 我做错了什么
  • 从API的文件存储系统下载worker上的文件的惯用方法是什么
  • default\u storage.open()
    命令不应该指向API的文件系统并能够下载它吗
    • 如果没有,我是否可以在worker上进行配置以支持此功能
  • 这仅仅是因为文件系统是共享的,而发生这种情况的原因是因为
    docker compose
    正在将它们分解为不同的环境吗

如果您在docker compose中,只需在api和worker之间创建一个共享docker卷,并将其装载到两个容器中的已知位置,如
/mnt/share
。确保将文件保存在API中,然后工作人员可以使用相同的模型访问它们,因为设置(例如,
MEDIA\u ROOT
)将使API和工作人员都指向
/mnt/share