我需要允许用户提交对非常非常大的作业的请求。我们说的是 100 GB 的内存和 20 小时的计算时间。这让我们公司花了很多钱,所以规定任何时候只能运行2个作业,已经有2个作业再请求新的作业会被拒绝(并通知用户服务器忙)。
我当前的解决方案使用 concurrent.futures 中的执行器,并且需要将 Apache 服务器设置为仅运行一个进程,从而降低响应速度(当前用户数非常少,所以暂时没问题)。
如果可能的话,我想为此使用 Celery,但我没有在文档中看到任何方式来完成此特定设置。
如何在 Django 应用程序的后台运行有限数量的作业,并在作业因服务器繁忙而被拒绝时通知用户?
最佳答案
针对这种特殊情况,我有两种解决方案,一种是 celery 的现成解决方案,另一种是您自己实现的。
- 你可以对 celery worker 做这样的事情。特别是,您只创建两个并发=1 的工作进程(或者好吧,一个并发=2,但那将是线程,而不是不同的进程),这样,只能完成两个工作异步地。现在你需要一种方法来在两个工作都被占用时引发异常,然后你使用 inspect , 计算事件任务的数量并在需要时抛出异常。如需实现,您可以查看 this SO post .
您可能还对 rate limits 感兴趣.
您可以使用所选的锁定解决方案自行完成所有工作。特别是,确保只有两个进程与 redis(和 redis-py)一起运行的一个很好的实现就像下面这样简单。 (考虑到你知道 Redis,因为你知道 celery )
from redis import StrictRedis redis = StrictRedis('localhost', '6379') locks = ['compute:lock1', 'compute:lock2'] for key in locks: lock = redis.lock(key, blocking_timeout=5) acquired = lock.acquire() if acquired: do_huge_computation() lock.release() break print("Gonna try next possible slot") if not acquired: raise SystemLimitsReached("Already at max capacity !")
这样你就可以确保系统中只能存在两个正在运行的进程。第三个进程将在 lock.acquire()
行中阻塞 blocking_timeout 秒,如果锁定成功,则 acquired
将为 True,否则它是假的,你会告诉你的用户等待!
我过去某个时候有过同样的需求,我最终编写的代码类似于上面的解决方案。特别是
- 这具有尽可能少的竞争条件
- 易于阅读
- 不依赖于系统管理员,在负载下突然将工作人员的并发性增加一倍并炸毁整个系统。
- 您还可以实现每个用户的限制,这意味着每个用户可以有 2 个同时运行的作业,只需更改 compute:lock1< 中的锁定 key /em> 相应地 compute:userId:lock1 和 lock2。你不能用 Vanilla celery 做这个。
关于python - 用户启动的后台进程数量有限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39416623/