8

我在处理我正在处理的 python 项目时遇到问题(我通常使用 PHP/Java,所以缺乏一点知识)。基本上,我有一个使用 Flask 构建的 python 程序,它使用 Shopify Python API 将库存管理系统连接到 Shopify。

当用户通过 AJAX 请求触发功能时,我需要启动一个功能/流程,通过 Shopify API 更新客户 Shopify 商店中的产品。这大约需要 2 小时(约 7000 种产品,而且必须先从库存管理系统中提取它们)。问题是我需要一种方法来触发这个函数/进程,即使客户端关闭他们的浏览器,函数/进程也会继续运行。

如果有任何方法我可以用这个后台功能/进程的当前进度来更新前端,那将会膨胀。

如果有人知道任何图书馆或资源来实现这一点,将不胜感激。我有一个谷歌,但我能找到的所有解决方案似乎都是针对 CLI 脚本而不是 Web 脚本。

谢谢堆,科里:)

4

2 回答 2

8

通常你会创建一个任务并返回给用户一个他可以用来汇集所述任务状态的ID。

然后你会在另一个容器\进程\线程中处理任务。

Celery是一个 Python 库,可以帮助您进行设置。

另一种常见的解决方案是使用发布者/订阅者设计并使用分布式队列,例如 Kafka、RabbitMQ 甚至 Redis。

事实上,Celery 可以使用 RabbitMQ 或 Redis 作为其消息代理。

于 2020-05-18T20:30:40.327 回答
7

您需要异步处理此任务,因为它是一项长时间运行的作业,会显着降低 HTTP 响应的性能(如果您等到它完成)。

此外,您可能会注意到您需要在为您的 HTTP 请求提供服务的当前进程的单独进程中运行此任务。因为,Web 服务器(Gunicorn、uWSGI 等)将生成它们创建的进程并在需要时释放系统资源。您很容易出现通过 Ajax 启动的异步进程将被 Web 服务器中断和终止的情况,因为您关闭了浏览器(请求关闭)。所以,threading并不是coroutines完成这项任务的最佳工具。

这就是为什么有一些很酷Task queue的项目可以解决您的问题。我们可能会注意到:

  • Celery:(生产就绪解决方案)它是一个任务队列,专注于实时处理,同时还支持任务调度。与消息代理一起工作RedisRabbitMQ用作消息代理
  • RQ (Redis Queue) : RQ (Redis Queue) 是一个简单的 Python 库,用于对作业进行排队并在后台与工作人员一起处理它们。它由 Redis 支持,旨在降低进入门槛。它可以轻松集成到您的 Web 堆栈中。
  • Taskmaster:Taskmaster 是一个简单的分布式队列,设计用于处理大量一次性任务。
  • Huey:是一个基于 Redis 的任务队列,旨在为执行任务提供一个简单而灵活的框架。Huey 支持任务调度、类似 crontab 的重复任务、结果存储和发生故障时的自动重试。
  • Dramatiq:是 Celery 的快速可靠的替代品。它支持 RabbitMQ 和 Redis 作为消息代理。
  • APScheduler : Advanced Python Scheduler (APScheduler) 是一个 Python 库,可让您安排 Python 代码稍后执行,无论是一次还是定期执行。

还有很多 !

随着你的崛起,micro services你可以结合和的力量,Task queuescontainers可以构建一个单独的容器来处理你的长时间运行的任务(并根据你当前的情况更新你的数据库)。此外,如果您还不能使用micro services架构,您可以构建一个单独的服务器来处理这些任务,并使处理用户请求的 Web 服务器免于运行长时间运行的任务。

最后,您可以在您当前的网站中组合这些解决方案,如下所示:

  • 用户点击一个按钮。
  • Ajax 请求触发您的后端(通过 API 或其他方式)
  • 您在代理消息中安排一个任务以现在或稍后运行它(在单独的容器/VPS 中......)
  • 在您的后端,您检索Task ID任务的
  • 您返回Task IDby API 或其他任何内容,然后将其添加到会话 cookie 或处理启动流程的用户的单独表中。
  • 在某些 JS 中,您不断从您的后端请求任务的状态Task ID(在用户会话 cookie 中或在您的数据库中)
  • 即使用户关闭了他的浏览器,该任务也将继续其操作,直到它完成或引发异常。在您已经拥有的任务 ID 中,您可以轻松了解此任务的状态并将此信息发送给用户(在他再次登录时的视图中,通过电子邮件等......)

并且确保您可以改善这种情况!

于 2020-05-18T21:11:36.243 回答