我正在尝试使用I / O(HDD,网络......)构建一个从某些来源收集数据的系统
为此,我有一个启动收集器的类(控制器)。
每个收集器都是一个带有经典ETL过程(提取,转换和加载)的无限循环。
我想从界面(CLI,web ...)向收集器发送一些命令(停止,重新加载设置...),我不知道该怎么做。
例如,这是收集器的骨架:
class Collector(object):
def __init__(self):
self.reload_settings()
def reload_settings(self):
# Get the settings
# Set the settings as attributes
def process_data(self, data):
# Do something
def run(self):
while True:
data = retrieve_data()
self.process_data(data)
这是控制器的骨架:
class Controller(object):
def __init__(self, collectors):
self.collectors = collectors
def run(self):
for collector in collectors:
collector.run()
def reload_settings(self):
??
def stop(self):
??
是否有解决此问题的经典设计模式(Publish-subscribe,event loop,reactor ...)?解决这个问题的最佳方法是什么?
PD:显然,这将是一个多进程应用程序,将在一台机器上运行。答案 0 :(得分:1)
这里有多种选择,但它们归结为两种主要类型:协作(事件循环/反应器/协程/显式greenlet)或抢占(隐式greenlet /线程/多进程)。
首先需要对收藏家进行更多重组。它可以是一种很好的方法来使非确定性显式,或实现大规模并发,但这些似乎都不相关。第二个只需要将收集器粘贴在线程上,并使用一些同步机制来进行通信和共享数据。您似乎没有共享数据,并且您的通信很简单,而且对时间不敏感。所以,我选择了线程。
假设您想要使用一般意义上的线程,假设您的收集器受I / O限制并且您没有数十个,我会选择实际的线程。
所以,这是你可以写的一种方式:
class Collector(threading.Thread):
def __init__(self):
self._reload_settings()
self._need_reload = threading.Event()
self._need_stop = threading.Event()
def _reload_settings(self):
# Get the settings
# Set the settings as attributes
self._need_reload.clear()
def reload_settings(self):
self._need_reload.set()
def stop(self):
self._need_stop.set()
def process_data(self, data):
# Do something
def run(self):
while not self._need_stop.is_set():
if self._need_reload.is_set():
self._reload_settings()
data = retrieve_data()
self.process_data(data)
class Controller(object):
def __init__(self, collectors):
self.collectors = collectors
def run(self):
for collector in self.collectors:
collector.start()
def reload_settings(self):
for collector in self.collectors:
collector.reload_settings()
def stop(self):
for collector in self.collectors:
collector.stop()
for collector in self.collectors:
collector.join()
(虽然我会调用Controller.run
方法stop
,因为它不仅适用于Thread
使用的命名,而且适用于stdlib服务器类和其他类似的事情。)
答案 1 :(得分:0)
我会考虑将您的案例调整为基于套接字的客户端 - 服务器架构的可能性,其中Controller将实例化所需数量的收集器,每个收集器都在其自己的端口上侦听,并通过handle()方法以更优雅的方式处理接收到的数据服务器。数据来自各种I / O源的事实对此解决方案说得更多 - 您可以使用此体系结构的客户端部分来标准化DataSource - >收集器协议