问题
我们对来自用户输入的地理数据(称为“系统”)运行若干计算。有时一个系统需要10个位置进行计算,有时需要1000个以上。一个位置大约需要1秒的时间来计算,希望我们能在将来加快速度。我们目前通过在芹菜工人内部使用多处理Pool(来自billiard)来实现这一点。这是因为它100%地利用所有核心,但有两个问题:存在延迟连接(pipes,可能是到子进程)导致工作进程在达到最大打开文件限制时挂起(已调查过,但在工作了一天多后仍未找到解决方案)
我们不能把计算分散到多台机器上。在
为了解决这些问题,我可以将每个计算作为一个单独的芹菜任务运行。但是,我们也希望为用户“公平”安排这些计算,以便:
在小型系统(例如<;50个位置)上工作的用户不必等到大型系统(超过1000个位置)完成。系统越大,增加的等待时间对用户来说就越不重要(不管怎样,他们正在做其他事情,并且可以得到通知)。所以这类似于Weighted fair queueing。在
我还没有找到一个分布式的任务执行者来实现这种优先级的可能性。我错过了吗?我研究了Celery、RQ、Huey、MRQ、Pulsar Queue等,以及Luigi和{a8}之类的数据处理管道,但似乎没有一个能轻松实现这一点。在
其中大多数建议通过为优先级较高的队列添加更多的工人来创建优先级。然而,这不会起作用,因为工人们会开始争夺CPU时间。(RQ通过清空第一个传入队列的来实现这一点,然后再转到下一个队列)。在
拟议架构
我想象的是运行一个多处理程序,每个CPU有一个进程,以WFQ方式从多个Redis列表中获取数据,每个Redis列表都是一个特定的队列。在
这是正确的方法吗?当然,要使队列配置成为动态的(例如,还将其存储在Redis中,并在每个已处理的任务上重新加载),以及让事件监视能够深入了解情况,还有很多工作要做。在
其他想法:每个任务需要大约3MB的数据,来自Postgres,这对于系统中的每个位置都是相同的(或者至少每100个位置)。在当前的方法中,它驻留在共享内存中,每个进程都可以快速访问它。我可能需要在每台机器上设置一个本地Redis实例来缓存这些数据,所以不是每个进程都会一遍又一遍地获取数据。在
我一直在关注ZeroMQ,它有很多诱人的可能性,但除了监视之外,它似乎不太适合。还是我错了?在
更合理的做法是:将每个worker作为一个单独的程序运行,并使用类似于supervisor之类的东西来管理它,或者启动一个单独的程序,为每个CPU分配一个子进程(不需要CPU计数配置),还可以监视它的子进程是否被卡住?在
我们已经运行了RabbitMQ和Redis,所以我也可以对队列使用RMQ。在我看来,使用RMQ所获得的唯一好处是,通过使用确认,在工人崩溃时不会丢失任务,而代价是使用更困难的库/复杂的协议。在
还有其他建议吗?在