我们在异步接收请求的服务中使用来自concurrent.futures
的{{3}},并在进程池中进行实际的同步处理。
一旦我们遇到流程池耗尽的情况,那么新请求必须等到其他一些流程完成。
有没有办法询问进程池的当前用法?这将使我们能够监控他们的状态并进行适当的容量规划。
如果没有,是否有任何良好的替代流程池实现,其中包含支持此类监控/容量规划的异步接口?
答案 0 :(得分:11)
最简单的方法是使ProcessPoolExecutor
扩展所需的行为。以下示例维护stdlib接口,但不访问实现细节:
from concurrent.futures import ProcessPoolExecutor
class MyProcessPoolExecutor(ProcessPoolExecutor):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._running_workers = 0
def submit(self, *args, **kwargs):
future = super().submit(*args, **kwargs)
self._running_workers += 1
future.add_done_callback(self._worker_is_done)
return future
def _worker_is_done(self, future):
self._running_workers -= 1
def get_pool_usage(self):
return self._running_workers
答案 1 :(得分:2)
我最近以稍微不同的方式为自己解决了这个问题。简化,这就是我所做的:
因此,假设done()
是实际回调函数,在其他地方定义,则在我的主循环范围内定义以下内容:
bag = set()
def make_callback(b):
def callback(f):
nonlocal b
b.remove(f)
done(f)
return callback
对于我提交给ProcessPoolExecutor的每个未来f
,我添加了回调:
f.add_done_callback(make_callback(bag))
在任何时候,都可以通过查看bag
的内容来查看待处理和正在运行的期货列表,可选择使用未来running()
方法的结果进行过滤。 E.g:
print(*bag, sep='\n')
print('running:', *(f for f in bag if f.running()))
对于许多简单的用例,模块级的set变量可能与闭包一样好。