有限数量的用户启动的后台进程

Nat*_*enn 10 python django asynchronous background-process celery

我需要允许用户提交非常大的工作请求.我们正在谈论100千兆字节的内存和20小时的计算时间.这花费了我们公司很多钱,因此规定任何时候只能运行2个作业,并且当2个已经运行时请求新作业将被拒绝(并且用户通知服务器正忙).

我当前的解决方案使用来自concurrent.futures的Executor,并且需要将Apache服务器设置为仅运行一个进程,从而降低响应速度(当前用户数非常低,因此现在可以正常使用).

如果可能的话我想使用Celery,但我没有在文档中看到任何方法来完成这个特定的设置.

如何在Django应用程序中在后台运行有限数量的作业,并在作业因服务器繁忙而被拒绝时通知用户?

Spi*_*Xel 9

对于这个特殊情况我有两个解决方案,一个是芹菜的开箱即用解决方案,另一个是你自己实现的解决方案.

  1. 你可以用芹菜工人做这样的事情.特别是,您只创建两个并发= 1的工作进程(或者,一个并发= 2,但这将是线程,而不是不同的进程),这样,只能两个作业异步完成.现在,如果两个作业都被占用,则需要一种方法来引发异常,然后使用inspect来计算活动任务的数量,并在需要时抛出异常.为了实现,您可以查看此SO帖子.

您可能也对速率限制感兴趣.

  1. 您可以使用选择的锁定解决方案自己完成所有操作.特别是,确保只有两个进程使用redis(和redis-py)运行的一个很好的实现就像下面这样简单.(考虑到你知道redis,因为你知道芹菜)

    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 !")
    
    Run Code Online (Sandbox Code Playgroud)

这样,您可以确保系统中只能存在两个正在运行的进程.第三个过程将在该行块lock.acquire()BLOCKING_TIMEOUT秒,如果锁定成功,acquired将是真实的,否则它是错误的,你会告诉你的用户等待!

我在过去的某个时候有同样的要求,我最终编码的是上面的解决方案.特别是

  1. 这可能是最少的竞争条件
  2. 它很容易阅读
  3. 不依赖于系统管理员,突然使负载下的工作者的并发性加倍并炸毁整个系统.
  4. 您还可以实现每个用户的限制,这意味着每个用户可以同时运行2个作业,只需将锁​​定键从compute:lock1更改为compute:userId:lock1和lock2.你不能用香草芹菜做这个.