简体   繁体   English

ZeroMQ - 如果服务器没有响应,如何让客户端放弃并稍后尝试?

[英]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)

ZeroMQ supports .poll() to non-blocking test before .recv() ZeroMQ 支持.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 ] timeoutint [默认: 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。

ZeroMQ supports non-blocking, asynchronous mode for .recv() ZeroMQ 支持.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>-

ZeroMQ works on Archetype Pattern, not on "dumb"-socket ZeroMQ 适用于原型模式,而不适用于“哑”套接字

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM