控制具有多个PUSH客户端的PULL的inproc zmq recv顺序

时间:2013-08-28 07:56:44

标签: python zeromq

我正在使用inproc zmq套接字进行多线程数据共享。我有一个主线程的多个线程客户端;每个客户端都有一个PUSH套接字,主服务器有一个PULL套接字,作为所有客户端的接收器。在大多数情况下,每个客户端都是独立的,但我确实有一些适度的订单要求,因为一个客户端线程相当特殊。

以下是一些代码,说明了我的问题的变体:

import threading
import zmq

context = zmq.Context()

pull = context.socket(zmq.PULL)
pull.bind('inproc://my-socket')

def slave():
    global context
    push = context.socket(zmq.PUSH)
    push.connect('inproc://my-socket')

    for x in 'one two three'.split(' '):
        push.send('>>> '+x)
    #push.send('END')
    push.close()

def master():
    global context
    push = context.socket(zmq.PUSH)
    push.connect('inproc://my-socket')

    for x in 'one two three'.split(' '):
        push.send(x)

    x = threading.Thread(target=slave)
    x.start()

    while x.is_alive():
        pass

    push.send('END')
    push.close()

thread = threading.Thread(target=master)
thread.start()

while True:
    if pull.poll():
        x = pull.recv()
        if x == 'END':
            print 'END - exiting'
            break
        print x

在主线程发送主要负载之后完全启动从属线程的事实使我期望从属数据之前的所有主数据。然而,事实并非如此。考虑以下输出(实际上,顺序不一致,但我确实得到了这个顺序):

$ python zmq_threads.py 
one
two
>>> one
three
>>> two
END - exiting

我可靠地想要下面的顺序,我相信这个顺序是主要/从属安排强制的,只要发送去

$ python zmq_threads.py 
one
two
three
>>> one
>>> two
>>> three
END - exiting

考虑一下,我可以看到多个套接字客户端不会承诺这种同步。但是,感觉我应该能够以某种方式冲洗某些东西以强制recv的顺序(特别是使用inproc传输)。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我通过让从属线程使用在主线程中接收并发送到主程序的不同套接字来解决这个问题。从理论上讲,我认为可以在这里使用STREAMER设备将inproc:// my-socket-2连接到inproc:// my-socket,但我认为我没有任何更多的顺序保证我只是抛出另一个线程混合主持STREAMER。

这是我的问题代码与所示技术的另一个再现。在所有情况下,我发现需要一个'END'信标而不是很烦人,但我不知道是否有更好的zmq / thread机制。

import threading
import zmq

context = zmq.Context()

pull = context.socket(zmq.PULL)
pull.bind('inproc://my-socket')

def slave():
    global context
    push = context.socket(zmq.PUSH)
    push.connect('inproc://my-socket-2')

    for x in 'one two three'.split(' '):
        push.send('>>> '+x)
    push.send('END')
    push.close()

def master():
    global context
    push = context.socket(zmq.PUSH)
    push.connect('inproc://my-socket')

    for x in 'one two three'.split(' '):
        push.send(x)

    slaved_pull = context.socket(zmq.PULL)
    slaved_pull.bind('inproc://my-socket-2')
    x = threading.Thread(target=slave)
    x.start()

    while True:
        if slaved_pull.poll():
            x = slaved_pull.recv()
            if x == 'END':
                #print 'END - exiting'
                break
            push.send(x)

    push.send('END')
    push.close()

thread = threading.Thread(target=master)
thread.start()

while True:
    if pull.poll():
        x = pull.recv()
        if x == 'END':
            print 'END - exiting'
            break
        print x