Python multithreaded ZeroMQ REQ-REP

后端 未结 1 537
无人共我
无人共我 2020-12-17 05:32

I am looking to implement a REQ-REP pattern with Python and ZeroMQ using multithreading.

With Python, I can create a new thread when a new client connects to the ser

相关标签:
1条回答
  • 2020-12-17 05:59

    Yes, ZeroMQ is a powerfull Can-Do toolbox

    However, the major surprise will be, that ZeroMQ <socket>-s are by far more structured than their plain counterparts, you use in the sample.

    { aZmqContext -> aZmqSocket -> aBehavioralPrimitive }

    ZeroMQ builds a remarkable, abstraction-rich framework, under a hood of a "singleton" ZMQ-Context, which is (and shall remain) the only thing used as "shared".

    Threads shall not "share" any other "derived" objects, the less any their state, as there is a strong distributed-responsibility framework architecture implemented, both in the sake of clean-design and a high performance & low-latency.

    For all ZMQ-Socket-s one shall rather imagine a much smarter, layered sub-structure, where one receives off-loaded worries about I/O-activities ( managed inside ZMQ-Context responsibility -- thus keep-alive issues, timing issues and fair-queue buffering / select-polling issues simply cease to be visible for you ... ), with one sort of a formal communication pattern behaviour ( given by a chosen ZMQ-Socket-type archetype ).

    Finally

    ZeroMQ and similarly nanomsg libraries are rather LEGO-alike projects, that empower you, as an architect & designer, more, than one typically realises at the very beginning.

    enter image description here

    One thus can focus on distributed-system behaviour, as opposed to lose time and energy on solving just-another-socket-messaging-[nightmare].

    ( Definitely worth to have a look into both books from Pieter Hintjens, co-father of the ZeroMQ. There you find plenty Aha!-moments on this great subject. )

    ... and as a cherry on a cake -- you get all of this as a Transport-agnostic, universal environment, whether passing some messages on inproc://, other over ipc:// and also in parallel listening / speaking over tcp:// layers.

    EDIT#12014-08-19 17:00 [UTC+0000]

    Kindly check comments below and further review your -- both elementary and advanced -- design-options for a <trivial-failure-prone>-spin-off processing, for a <load-balanced>-REP-worker queueing, for a <scale-able>-distributed processing and a <_faul-resilient_mode_>-REP-worker binary-start shaded processing.

    No heap of mock-up SLOC(s), no single code-sample will do a One-Size-Fits-All.

    This is exponentially valid in designing distributed messaging systems.

    Sorry to say that.

    Hurts, but true.

    """REQ/REP modified with QUEUE/ROUTER/DEALER add-on ---------------------------
    
       Multithreaded Hello World server
    
       Author: Guillaume Aubert (gaubert) <guillaume(dot)aubert(at)gmail(dot)com>
    
    """
    import time
    import threading
    import zmq
    
    print "ZeroMQ version sanity-check: ", zmq.__version__
    
    def aWorker_asRoutine( aWorker_URL, aContext = None ):
        """Worker routine"""
        #Context to get inherited or create a new one trick------------------------------
        aContext = aContext or zmq.Context.instance()
    
        # Socket to talk to dispatcher --------------------------------------------------
        socket = aContext.socket( zmq.REP )
    
        socket.connect( aWorker_URL )
    
        while True:
    
            string  = socket.recv()
    
            print( "Received request: [ %s ]" % ( string ) )
    
            # do some 'work' -----------------------------------------------------------
            time.sleep(1)
    
            #send reply back to client, who asked --------------------------------------
            socket.send( b"World" )
    
    def main():
        """Server routine"""
    
        url_worker = "inproc://workers"
        url_client = "tcp://*:5555"
    
        # Prepare our context and sockets ------------------------------------------------
        aLocalhostCentralContext = zmq.Context.instance()
    
        # Socket to talk to clients ------------------------------------------------------
        clients = aLocalhostCentralContext.socket( zmq.ROUTER )
        clients.bind( url_client )
    
        # Socket to talk to workers ------------------------------------------------------
        workers = aLocalhostCentralContext.socket( zmq.DEALER )
        workers.bind( url_worker )
    
        # --------------------------------------------------------------------||||||||||||--
        # Launch pool of worker threads --------------< or spin-off by one in OnDemandMODE >
        for i in range(5):
            thread = threading.Thread( target = aWorker_asRoutine, args = ( url_worker, ) )
            thread.start()
    
        zmq.device( zmq.QUEUE, clients, workers )
    
        # ----------------------|||||||||||||||------------------------< a fair practice >--
        # We never get here but clean up anyhow
        clients.close()
        workers.close()
        aLocalhostCentralContext.term()
    
    if __name__ == "__main__":
        main()
    
    0 讨论(0)
提交回复
热议问题