pyzmq提升REQ/REP模式可靠性


  (原文在zguide,有兴趣慢慢看)

    提升REQ/REP模式的客户端侧可靠性,由于在此模式下,客户端与服务端严格遵循你一下我一下的乒乓规则,当然现实中不可能这么配合,比如服务器突然挂了,客户端就会阻塞在socket.recv(),然后过段时间,服务器又ok了,客户端也自动重连。但是有的场景客户端需要及时知道服务端状况而不是在那一直等,需要返回个错误之类。

    手册提供这种方法:

伦理片 http://www.dotdy.com/

    不知道作者起这名字有啥含义,海盗?客户端代码:

Python代码   收藏代码
  1. import sys  
  2. import zmq  
  3.   
  4. REQUEST_TIMEOUT = 2500  
  5. REQUEST_RETRIES = 3  
  6. SERVER_ENDPOINT = "tcp://localhost:5555"  
  7.   
  8. context = zmq.Context(1)  
  9.   
  10. print "I: Connecting to server…"  
  11. client = context.socket(zmq.REQ)  
  12. client.connect(SERVER_ENDPOINT)  
  13.   
  14. poll = zmq.Poller()  
  15. poll.register(client, zmq.POLLIN)  
  16.   
  17. sequence = 0  
  18. retries_left = REQUEST_RETRIES  
  19. while retries_left:  
  20.     sequence += 1  
  21.     request = str(sequence)  
  22.     print "I: Sending (%s)" % request  
  23.     client.send(request)  
  24.   
  25.     expect_reply = True  
  26.     while expect_reply:  
  27.         socks = dict(poll.poll(REQUEST_TIMEOUT))  
  28.         if socks.get(client) == zmq.POLLIN:  
  29.             reply = client.recv()  
  30.             if not reply:  
  31.                 break  
  32.             if int(reply) == sequence:  
  33.                 print "I: Server replied OK (%s)" % reply  
  34.                 retries_left = REQUEST_RETRIES  
  35.                 expect_reply = False  
  36.             else:  
  37.                 print "E: Malformed reply from server: %s" % reply  
  38.   
  39.         else:  
  40.             print "W: No response from server, retrying…"  
  41.             # Socket is confused. Close and remove it.  
  42.             client.setsockopt(zmq.LINGER, 0)  
  43.             client.close()  
  44.             poll.unregister(client)  
  45.             retries_left -= 1  
  46.             if retries_left == 0
  47.             # Create new connection  
  48.             client = context.socket(zmq.REQ)  
  49.             client.connect(SERVER_ENDPOINT)  
  50.             poll.register(client, zmq.POLLIN)  
  51.             client.send(request)  
  52.   
  53. context.term()  

    重点是:使用poll.poll(REQUEST_TIMEOUT),来执行一个限时读操作,如果时间段内该REQ socket没收到数据,视作服务端故障,这时就尝试先关闭当前socket,然后重连服务端,重发request。

 

  另外,注意client.setsockopt(zmq.LINGER, 0)设置linger为0,即马上丢掉socket中未处理的消息,否则context,term()啥时能执行完就不知道了。

  模拟一个会出错的服务端:

影音先锋电影 http://www.iskdy.com/

Python代码   收藏代码
  1. #coding=utf-8  
  2.   
  3. from random import randint  
  4. import time  
  5. import zmq  
  6.   
  7. context = zmq.Context(1)  
  8. server = context.socket(zmq.REP)  
  9. server.bind("tcp://*:5555")  
  10.   
  11. cycles = 0  
  12. while True:  
  13.     request = server.recv()  
  14.     cycles += 1  
  15.   
  16.     # Simulate various problems, after a few cycles  
  17.     if cycles > 3 and randint(03) == 0:  
  18.         print "I: Simulating a crash"  
  19.         break  
  20.     elif cycles > 3 and randint(03) == 0:  
  21.         print "I: Simulating CPU overload"  
  22.         time.sleep(2)  
  23.         break  
  24.   
  25.     print "I: Normal request (%s)" % request  
  26.     time.sleep(1# Do some heavy work  
  27.     server.send(request)  
  28.   
  29. server.close()  
  30. context.term()  

   看下运行结果:

Java代码   收藏代码
  1. 服务端:  
  2. I: Normal request (1)  
  3. I: Normal request (2)  
  4. I: Normal request (3)  
  5. I: Simulating a crash  
  6. [Finished in 5.5s]  
  7. 客户端:  

  其实这个也不是提高可靠性吧,只是强化客户端的感知能力。 



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值