在 Django 中处理用户触发任务(如导入数据)的最佳方式

Best Way to Handle user triggered task (like import data) in Django

我需要您对我面临的挑战发表意见。我正在构建一个使用 Django 作为后端、PostgreSQL 作为我的数据库、GraphQL 作为我的 API 层和 React 作为我的前端框架的网站。网站托管在 Heroku 上。我写了一个 python 脚本让我登录到我的 gmail 帐户并根据预定义的条件解析几封电子邮件,并将解析的数据存储到 Google Sheet 中。现在,我希望脚本成为我网站的一部分,用户将在其中指定确切需要解析的内容(即过滤器),然后在 table 中显示解析的数据以检查解析任务的准确性。

我需要帮助的部分是如何构建这样的工作流程。以下是我在谷歌搜索后设法想出的一些想法:

  1. 生成一个 graphQL 突变,将 'task' 存储到任务模型中。存储新任务条目后,Django 信号将触发脚本。尚不确定 Signal 是否可以 运行 自定义 python 函数,但从我目前所读的内容来看,它似乎是可行的。
  2. 使用 Celery 异步地 运行 此任务。但是我不确定异步任务是否是我想要的,因为我需要在用户从前端触发该功能后立即将此任务 运行。但我在这里可能是错的。我也不确定我是否需要 Redis 来存储任务详细信息,或者我可以在 PostgreSQL 上完成。

实施此功能的最佳做法是什么?任务可以是任何东西,不一定是解析电子邮件;它也可以从 excel 导入数据。任何由用户生成的任务,而不是计划或重复的任务。

如果这个问题对你们中的一些人来说似乎微不足道,我提前道歉。我不是专业开发人员,上述项目是我提高技术技能和学习新技术的一种方式。

期待从您的经验中学习。

您可以将您的问题分解为以下步骤:

  1. 用户指定任务参数
  2. 系统执行任务
  3. 系统向用户显示结果

您可以执行所有这些操作:

  1. 一口气顺序同步;或
  2. 逐步异步。

同步

您可以在生成响应时运行您的脚本,但它会带来以下缺点:

  1. 服务器中处理您的请求的进程将阻塞,直到脚本完成。这可能会也可能不会影响同一服务器对其他请求的处理(这取决于正在处理的同时请求的数量、脚本的工作量等)
  2. 如果脚本运行时间过长,客户端(例如您的浏览器)甚至服务器都可能超时。您可以通过适当地配置您的服务器来在一定程度上解决这个问题。

然而,这种方法的美妙之处在于它的简单性。为此,您只需通过请求传递参数,服务器解析并执行脚本,然后 returns 您得到结果。

无需设置消息队列、任务调度程序或任何需要的东西。

异步

不过,理想情况下,对于长时间 运行ning 任务,最好在通常的请求-响应循环之外执行此操作,以获得以下优点:

  1. 响应请求的服务器实际上可以服务于其他请求。
  2. 有些脚本可能需要一段时间,有些您甚至不知道它是否会完成
  3. 脚本不再依赖于网络的可靠性(想象一下 运行 执行一项 昂贵的 任务,然后您的互联网连接会中断或只是断断续续;您将无法做任何事情)

这样做的缺点是现在您必须设置更多的东西,这增加了项目的复杂性和失败点。

生产者-消费者

无论您选择什么,通常最好遵循生产者-消费者模式:

  1. 生产者创建任务并将它们放入队列
  2. 消费者从队列中取出一个任务并执行它

生产者基本上就是你,用户。您指定任务和该任务涉及的参数。

这个队列可以是任何数据存储:像 Redis 这样的内存数据存储;像 RabbitMQ 这样的消息队列;或像 PostgreSQL 这样的关系数据库管理系统。

使用者是执行这些任务的脚本。 运行宁 consumer/script 有多种方法:通过 Celery 就像你提到的那样 运行s 多个 worker 来执行通过队列传递的任务;通过一个简单的基于时间的作业调度程序,如 crontab;甚至您手动触发脚本

这个问题实际上并不简单,因为解决方案取决于您实际尝试执行的任务。最好评估约束、参数和实际任务来决定您将选择哪种方法。

但只是为了给你一个更相关的指导方针:

保持简单,除非您有令人信服的理由(例如,服务器出现故障,或者互联网连接在实践中不可靠),否则真的没有理由花哨。

任务阻塞越多,或者任务花费的时间越长,或者它通过网络对第三方 API 的依赖性越强,将其推送到后台进程增加可靠性和弹性就越有意义。

在您的电子邮件导入脚本中,我很可能会将其推送到后台:

  1. 有一个页面,您可以在其中向数据库添加任务
  2. 在任务详情页面中,显示任务详情,如果存在则在下方显示结果,否则显示“正在处理...”
  3. 有一个执行任务的脚本(在给定任务参数的情况下从 gmail 导入电子邮件)并将结果保存到数据库
  4. 通过 crontab
  5. 每隔几分钟将此脚本安排到 运行

是的,上面有副作用,比如 crontab 运行 同时多次执行脚本等,但如果不了解更多任务的具体细节,我不会详细介绍。