asynchronous - 在 python 中服务 web 请求,产生一个新的长时间运行的子进程
问题描述
我目前有一个 python 命令行应用程序,它使用 pythoninvoke
包来组织、列出和执行任务。有许多任务文件(由用户控制和创建,而不是我)。某些任务文件的执行时间可能超过一个小时。每个任务实际上是一个测试脚本/程序。invoke
在列出/执行任务文件中的所有任务(我们称其为testsuite)或仅其中一堆(任务集合)或单个任务中很有用。(拥有大量松散的脚本并以用户想要的方式组织、列出和运行它们将是一项艰巨的任务,因此invoke
)。但是,invoke
不能用作库。它不提供可用于列出和运行测试任务的 API。所以我被迫跑invoke
作为命令行程序的子进程中的shell命令。我将(通过execl()
)当前进程替换为,invoke
因为一旦控制权传递给invoke
,就无需返回父进程。目前还不错。。
现在,要求该命令行程序可以从 Web 应用程序中调用。所以我需要将这个 cmdline 程序包装在一个宁静的 http API 中。我决定用它bottle.py
来保持简单。
我知道长时间运行的测试套件(任务)必须在 http 请求/响应周期之外完成。但我无法最终确定如何去做(可能。我可能是过度思考)。但这就是我想要的...
- 任务由用户编写。它们总是同步的,它们可以
sleep
或通过subprocess.run()
. - 应用程序是内部的,它不会被大量请求轰炸。最大用户数 10.
- 但是每个请求(运行任务的类型)都需要几分钟,在某些情况下需要 > 小时才能完成。在此期间的新请求不应阻塞。
- 调用应用程序(在不同主机上运行)需要向浏览器 UI 报告运行任务的进度。('进度条')
- 能够与正在运行的任务进行通信并从浏览器 UI 中“取消”它。
在上述情况下,我说得对吗..
- 因为必须为请求生成一个新的“进程”(由于使用当前代码
subprocess
和excl
在当前代码中),所以它排除了使用任何类型的“线程”(操作系统线程、greenlets、gevent)? - 使用任何异步库(Web 框架、Web/http 服务器或应用程序代码)不会有太大帮助,因为无论如何每个运行请求都必须是一个新进程?
- 当请求进来时,该进程将如何产生?让 web/htpp 服务器(gunicorn?)来做?还是我的应用程序必须自己分叉?
- 在这种情况下,'gunicorn' 是一个不错的选择吗?
- 我有一种感觉,用户可能还会要求安排任务/测试的能力。我最终可能会使用某种任务队列。我读过“huey”,觉得它轻巧简单,可以满足我的需求。(没有redis/芹菜)。但是任何任务队列也意味着要管理一个单独的消费者进程?更多的运动部件混合在一起。
- “进度条”功能意味着,子进程必须在某处不断更新其进度,并且调用应用程序必须从那里读取。无论如何,这是否需要“任务队列”?
有很多关于所有这些的材料,如果是的话,我已经阅读了很多。但它仍然让我不清楚如何准确地实现我的要求。任何方向/指针将不胜感激。我也很感激任何关于“不使用”的建议。
解决方案
如果您需要一些非常简单的东西,那么您可以围绕任务假脱机程序(运行任务的 Linux 工具)编写一个包装器https://vicerveza.homeunix.net/~viric/soft/ts/(尤其是https://vicerveza.homeunix.net /~viric/soft/ts/article_linux_com.html了解更多详情)
否则,最好切换到 uwsgi spooler、rq 和 redis 或 celery 和 rabbitmq(因为 redis 在一定程度上可以工作)。
推荐阅读
- javascript - 如何制作可以访问对象项的自定义函数?
- android - Flutter InAppWebview:当我触摸任何地方时,相机就会打开
- ios - UITableView - 平滑展开和折叠显示 UICollectionView
- sqlite - 使用 SQLite 的 Entity Framework Core 5.0.0 blob 流式传输?
- docker - Webpack 无法在 Github Action Docker 容器中写入构建文件
- sql - 使用窗函数 sum 遇到除以零错误
- flutter - 如何通过使用 Bloc Cubit 和 Bloc Consumer 使用来自 fire 存储的依赖注入来等待数据到来
- python - pyinstaller 的 Cloudscraper 问题
- python - 如何在 SageMaker 中的 model.tar.gz 上创建模型?
- java - liquibaseDiffChangelog gradle 任务因 java.lang.UnsupportedOperationException 出错:应用程序必须提供 JDBC 连接