zeroMQ初体验-19.应答模式进阶(五)-异步式应答

来源:互联网 发布:苹果电脑优缺点知乎 编辑:程序博客网 时间:2024/05/29 12:25
 恩,这应该算是比较实用的部分了。

模式图:


Python代码 复制代码 收藏代码
  1. import zmq   
  2. import threading   
  3. import time   
  4. from random import choice   
  5.   
  6. class ClientTask(threading.Thread):   
  7.     """ClientTask"""  
  8.     def init(self):   
  9.         threading.Thread.init (self)   
  10.   
  11.     def run(self):   
  12.         context = zmq.Context()   
  13.         socket = context.socket(zmq.XREQ)   
  14.         identity = 'worker-%d' % (choice([0,1,2,3,4,5,6,7,8,9]))   
  15.         socket.setsockopt(zmq.IDENTITY, identity )   
  16.         socket.connect('tcp://localhost:5570')   
  17.         print'Client %s started' % (identity)   
  18.         poll = zmq.Poller()   
  19.         poll.register(socket, zmq.POLLIN)   
  20.         reqs = 0  
  21.         whileTrue:   
  22.             for i in xrange(5):   
  23.                 sockets = dict(poll.poll(1000))   
  24.                 if socket in sockets:   
  25.                     if sockets[socket] == zmq.POLLIN:   
  26.                         msg = socket.recv()   
  27.                         print'%s: %s\n' % (identity, msg)   
  28.                         del msg   
  29.             reqs = reqs + 1  
  30.             print'Req #%d sent..' % (reqs)   
  31.             socket.send('request #%d' % (reqs))   
  32.   
  33.         socket.close()   
  34.         context.term()   
  35.   
  36. class ServerTask(threading.Thread):   
  37.     """ServerTask"""  
  38.     def init(self):   
  39.         threading.Thread.init (self)   
  40.   
  41.     def run(self):   
  42.         context = zmq.Context()   
  43.         frontend = context.socket(zmq.XREP)   
  44.         frontend.bind('tcp://*:5570')   
  45.   
  46.         backend = context.socket(zmq.XREQ)   
  47.         backend.bind('inproc://backend')   
  48.   
  49.         workers = []   
  50.         for i in xrange(5):   
  51.             worker = ServerWorker(context)   
  52.             worker.start()   
  53.             workers.append(worker)   
  54.   
  55.         poll = zmq.Poller()   
  56.         poll.register(frontend, zmq.POLLIN)   
  57.         poll.register(backend,  zmq.POLLIN)   
  58.   
  59.         whileTrue:   
  60.             sockets = dict(poll.poll())   
  61.             if frontend in sockets:   
  62.                 if sockets[frontend] == zmq.POLLIN:   
  63.                     msg = frontend.recv()   
  64.                     print'Server received %s' % (msg)   
  65.                     backend.send(msg)   
  66.             if backend in sockets:   
  67.                 if sockets[backend] == zmq.POLLIN:   
  68.                     msg = backend.recv()   
  69.                     frontend.send(msg)   
  70.   
  71.         frontend.close()   
  72.         backend.close()   
  73.         context.term()   
  74.     
  75. class ServerWorker(threading.Thread):   
  76.     """ServerWorker"""  
  77.     def init(self, context):   
  78.         threading.Thread.init (self)   
  79.         self.context = context   
  80.   
  81.     def run(self):   
  82.         worker = self.context.socket(zmq.XREQ)   
  83.         worker.connect('inproc://backend')   
  84.         print'Worker started'  
  85.         whileTrue:   
  86.             msg = worker.recv()   
  87.             print'Worker received %s' % (msg)   
  88.             replies = choice(xrange(5))   
  89.             for i in xrange(replies):   
  90.                 time.sleep(1/choice(range(1,10)))   
  91.                 worker.send(msg)   
  92.             del msg   
  93.   
  94.         worker.close()   
  95.   
  96. def main():   
  97.     """main function"""  
  98.     server = ServerTask()   
  99.     server.start()   
  100.     for i in xrange(3):   
  101.         client = ClientTask()   
  102.         client.start()   
  103.        
  104.     server.join()   
  105.        
  106.   
  107. if name == "main":   
  108.     main()  


作为一个异步的服务器,详图应该是这样的:


这里的数据传递顺序是这样的:
Java代码 复制代码 收藏代码
  1. client        server     frontend     worker   
  2.    [ XREQ ]<---->[ XREP <----> XREQ <----> XREQ ]   
  3.            1 part       2 parts     2 parts  


在这里有可能碰到一个比较经典的c/s问题:
c端太多,耗尽s端资源怎么办?
这就需要靠谱些的机制了,比如通过“心跳”来确定是否应该释放这个c端的资源等。当然,那就是另外一个话题了。