我在Python中实现了一个“网络服务”超类,如下所示:
class NetworkService (threading.Thread):
"""
Implements a multithreaded network service
"""
# Class Globals (ie, C++ class static)
ZmqContext = zmq.Context.instance()
# ==========================================================================================
# Class Mechanics
# ==========================================================================================
def __init__(self, name, port, conc=4):
"""
Network service initilization
"""
self.service_name = name
self.service_port = port
self.concurrency = conc
self.handler_url = "inproc://" + name
self.client_url = "tcp://*:" + str(port)
self.shutdown = True # Cleared in run()
self.thread = {}
super(NetworkService, self).__init__()
# ==========================================================================================
# Class Operation
# ==========================================================================================
def run(self): # Called [only] by threading.Thread.start()
self.shutdown = False
clients = NetworkService.ZmqContext.socket(zmq.ROUTER)
clients.bind(self.client_url)
handlers = NetworkService.ZmqContext.socket(zmq.DEALER)
handlers.bind(self.handler_url)
for i in range(self.concurrency):
self.thread[i] = threading.Thread(target = self.handler, name = self.service_name + str(i))
self.thread[i].daemon = True
self.thread[i].start()
zmq.proxy(clients, handlers)
clients.close()
handlers.close()
def terminate(self):
self.shutdown = True
def handler(self):
socket = NetworkService.ZmqContext.socket(zmq.REP)
socket.connect(self.handler_url)
iam = repr(get_pids()[2])
log.info("nsh@%s is up", iam)
while not self.shutdown:
string = socket.recv()
toe = datetime.utcnow()
command = pickle.loads(string)
reply = self.protocol(command)
string = pickle.dumps(reply)
socket.send(string)
def protocol(self, command): # Override this in subclass
reply = {}
reply["success"] = False
reply["detail"] = "No protocol defined (NetworkService.protocol(...) not overridden)"
if "ident" in command:
reply["ident"] = command["ident"]
return reply
问题在于“ zmq.proxy(clients, handlers)
”:我似乎无法完成它。永远。如果所有处理程序都终止,则zmq.proxy()
仍然不会返回。我不介意创建一个独立的线程来运行代理,但这是一个守护进程,我希望能够干净地关闭。
我在文档中读到这是zmq.proxy
的正确行为,但对我来说似乎不正确; - }。
任何人都可以推荐在处理程序线程终止后可以关闭的近似等价物吗?
答案 0 :(得分:1)
API基本上意味着您必须终止上下文。您可以在具有共享上下文的单独线程中运行代理,然后终止它,除了zmq.ContextTerminated。
try:
zmq.proxy(self.frontend, self.backend)
except zmq.ContextTerminated:
# cleanup if needed