[英]ZeroMQ - how to make a CLIENT to give up and try at a later time if the SERVER doesn't respond?
Lets say I have a very simple Client/Server model, using REQ/REP
from ZeroMQ.假设我有一个非常简单的客户端/服务器模型,使用来自 ZeroMQ 的
REQ/REP
。 See python code below.请参阅下面的python代码。
In the code below the client will wait forever, but I want the client to give up (lets say after 20 seconds) and move on with its life if it doesn't get a response.在下面的代码中,客户端将永远等待,但我希望客户端放弃(假设在 20 秒后)并继续其生命,如果它没有得到响应。 The server could be down, the router unplugged, the WiFi is not working.
服务器可能已关闭,路由器已拔下,WiFi 无法正常工作。 I really don't or should care why.
我真的不或者应该关心为什么。
Then at a later time, I'll have the client try again and it could be a completely different request.稍后,我会让客户再试一次,这可能是一个完全不同的请求。
But I fear I'll cross an old request, get things out of order, cause more problems.但我担心我会跨越一个旧的要求,让事情变得混乱,引起更多的问题。
Does anyone know how to do this gracefully?有谁知道如何优雅地做到这一点? I've been racking my brain on a simple solution.
我一直在绞尽脑汁想一个简单的解决方案。
SIMPLE CLIENT CODE简单的客户端代码
#!/usr/bin/env python3
import zmq
from time import sleep
# CREATE SOCKET - Client (USING zmq.REQ)
my_client_context = zmq.Context()
my_client_socket = my_client_context.socket(zmq.REQ)
my_client_socket.connect('tcp://127.0.0.1:5557')
# [REQ]uest AND [REP]ly
to_server = b"Hi"
my_client_socket.send(to_server)
from_server = my_client_socket.recv()
print(from_server)
sleep(2)
# REQuest AND REPort
to_server = b"blah"
my_client_socket.send(to_server)
from_server = my_client_socket.recv()
print(from_server)
SIMPLE SERVER CODE简单的服务器代码
#!/usr/bin/env python3
import zmq
# CREATE SOCKET - Server (USING zmq.REP)
my_server_context = zmq.Context()
my_server_socket = my_server_context.socket(zmq.REP)
my_server_socket.bind('tcp://127.0.0.1:5557')
# LISTEN ON SOCKET
while True:
msg = my_server_socket.recv()
if msg == b'Hi':
to_client = b"Well hello to you"
my_server_socket.send(to_client)
else:
to_client = b"Not sure what you want"
my_server_socket.send(to_client)
.poll()
to non-blocking test before .recv()
.poll()
在.recv()
之前进行非阻塞测试One can use .poll()
可以使用
.poll()
.poll( timeout = None, flags = zmq.POLLIN ) # poll the socket for events
The default is to poll forever for incoming events.
默认是永远轮询传入事件。 Timeout is in milliseconds, if specified.
如果指定,超时以毫秒为单位。
Parameters:
参数:
timeout
:int
[default:None
]timeout
:int
[默认:None
]The timeout ( in milliseconds ) to wait for an event.
等待事件的超时时间(以毫秒为单位)。 If unspecified (or specified
None
), will wait forever for an event.如果未指定(或指定
None
),将永远等待事件。
flags
: bitfield (int
) [default:POLLIN
]flags
:位域(int
)[默认值:POLLIN
]The event flags to poll for ( any combination of
POLLIN | POLLOUT
).要轮询的事件标志(
POLLIN | POLLOUT
任意组合)。 The default is to check for incoming events (POLLIN
).默认是检查传入事件 (
POLLIN
)。Returns:
返回:
events
: bitfield (int
)events
:位域(int
)The events that are ready and waiting.
准备和等待的事件。 Will be 0 if no events were ready by the time timeout was reached.
如果到超时时间没有事件准备好,则为 0。
.recv()
.recv()
的非阻塞、异步模式so may build one's own, non-blocking, soft-RT-tuned .recv()
busy loop.所以可以构建自己的、非阻塞的、软 RT 调优的
.recv()
忙循环。
while not_SIG_KILL_yet: # main-<LOOP> -<o>-<o>-<o>-<o>-<o>-<o>-<o>-<o>-<o>-
try: # TRY: an-outer-most-<ExceptionWRAPPER> for KeyboardInterrupt
''' ............................................................ 250 msec sample-rate <loop>-task ____________________________________________________________________________'''
try:
maybeRECV = my_client_socket.recv( zmq.NOBLOCK )
# Handle .recv() data
except:
# Handle ZMQError EAGAIN
# .INC failed attempts COUNTER
# .IF >
if ( COUNTER > aTresholdToGiveUp ):
not_SIG_KILL_yet = False
continue
# GIVE CPU-a-NAP -------------------- may be segmented + EXC-handler
# ------------------------------------------------------------------
except KeyboardInterrupt:
not_SIG_KILL_yet = False
pass
# <EoW>-----------------# main-<LOOP> -<o>-<o>-<o>-<o>-<o>-<o>-<o>-<o>-<o>-
Thus being afraid to meet "old"-[ REP
]-answer ( still hanging ( and it must hang there, mustn't it? ) on the SERVER-side in the internal Queue ) is correct as the REQ/REP
-pattern is exactly doing that by-definition.因此,害怕在内部队列的服务器端遇到“旧”-[
REP
]-答案(仍然挂着(它必须挂在那里,不是吗?)是正确的,因为REQ/REP
模式是正是按照定义来做的。
The CLIENT side has the right to gracefully close the associated resources and send SERVER an indication of clearing the circus. CLIENT 端有权优雅地关闭相关资源,并向 SERVER 发送清除马戏团的指示。
ZeroMQ support very dynamic set-up/tear-downs of the ground elements and it is a fair manner not to leave communication-counterparty ( SERVER in this case ) in any doubts about what the communication-peer intended to do. ZeroMQ 支持基础元素的非常动态的设置/拆卸,并且不让通信对方(在本例中为 SERVER)对通信对等方打算做什么有任何疑问是一种公平的方式。
Read details about:阅读有关以下内容的详细信息:
my_client_context.setsockopt( zmq.LINGER, 0 ) # do not wait for anything
my_client_socket.close() # statefull close
my_client_context.term() # graceful termination / release of resources ( no MEM leaks )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.