Quantcast
Channel: Active questions tagged zeromq - Stack Overflow
Viewing all articles
Browse latest Browse all 193

ZeroMQ Load Balancing Broker 3 example, but with multiprocessing instead of multithreading in Python

$
0
0

I'm following along in the ZeroMQ book, and trying the Python examples. I'm at lbbroker3.py, and trying to switch it from using multithreading to multiprocessing in Python 3. I was looking at another python ZeroMQ multiprocessing example online from a blog, and tried to incorporate the least amount of changes.

Whenever I run my code, it hangs at joining the first worker thread. The worker thread seems to be hung on "socket.recv_multipart()".

######################################################################HERE IS MY CODE:

import zmqfrom zmq.eventloop.ioloop import IOLoopfrom zmq.eventloop.zmqstream import ZMQStreamfrom multiprocessing import Queue, Process, Eventimport timefrom time import sleepNUM_CLIENTS = 12NUM_WORKERS = 4def client_proc(client_url, ident):    # Basic request-reply client using REQ socket    context = zmq.Context.instance()    socket = context.socket(zmq.REQ)    socket.identity = (u"Client-%d" % (ident)).encode('ascii')    socket.connect(client_url)    # Send request, get reply:    socket.send(b"HELLO")    reply = socket.recv()    print("%s: %s\n" % (socket.identity.decode('ascii'),                        reply.decode('ascii')), end='')def worker_proc(ident, worker_url):    # Before doing work, set up IPC via ZeroMQ    # Note: Worker uses local REQ socket to connect to ROUTER socket in broker    context = zmq.Context.instance()    socket = context.socket(zmq.REQ)    socket.identity = (u"Worker-%d" % (ident)).encode('ascii')    socket.connect(worker_url)    # Tell the broker we are ready for work    socket.send(b"READY")    try:        while True:            address, empty, request = socket.recv_multipart() # This line is where            # the program hangs upon attempting to join first worker process.            print("%s: %s\n" % (socket.identity.decode('ascii'),                                request.decode('ascii')), end='')            socket.send_multipart([address, b'', b'OK'])    except zmq.ContextTerminated:        # context terminated so quit silently        returnclass LRUQueue(object):    # LRUQueue class using ZMQStream/IOLoop for event dispatching    def __init__(self, backend_socket, frontend_socket):        self.available_workers = 0        self.is_workers_ready = False        self.workers = []        self.client_nbr = NUM_CLIENTS        self.backend = ZMQStream(backend_socket)        self.frontend = ZMQStream(frontend_socket)        self.backend.on_recv(self.handle_backend)        self.loop = IOLoop.instance()    def handle_backend(self, msg):        # Queue worker address for LRU routing        worker_addr, empty, client_addr = msg[:3]        assert self.available_workers < NUM_WORKERS        # add worker back to the list of workers        self.available_workers += 1        self.is_workers_ready = True        self.workers.append(worker_addr)        # 2nd frame is empty        assert empty == b""        # Third frame is READY or else a client reply address        # If client reply, send rest back to frontend        if client_addr != b"READY":            empty, reply = msg[3:]            # Following frame is empty            assert empty == b""            self.frontend.send_multipart([client_addr, b'', reply])            self.client_nbr -= 1            print(f"num clients: {self.client_nbr}")            if self.client_nbr == 0:                # Exit after N messages                self.loop.add_timeout(time.time() + 1, self.loop.stop)        if self.is_workers_ready:            # When at least 1 worker ready, start accepting frontend msgs            self.frontend.on_recv(self.handle_frontend)    def handle_frontend(self, msg):        # Now get next client request, route to LRU worker        # Client request is [address][empty][request]        client_addr, empty, request = msg        assert empty == b""        # Dequeue and drop the next worker address        self.available_workers -= 1        worker_id = self.workers.pop()        self.backend.send_multipart([worker_id, b'', client_addr, b'', request])        if self.available_workers == 0:            # stop receiving until workers become available again            self.is_workers_ready = False            self.frontend.stop_on_recv()def main():    #print("Number of CPU cores: ", multiprocessing.cpu_count())    #num_workers = multiprocessing.cpu_count() - 1    #num_workers = 2    url_worker = "ipc://backend.ipc"    url_client = "ipc://frontend.ipc"    # Prepare our ZMQ context and sockets    context = zmq.Context()    frontend = context.socket(zmq.ROUTER)    frontend.bind(url_client)    backend = context.socket(zmq.ROUTER)    backend.bind(url_worker)    ## Generate grid of Mandelbrot values    #gridvals = generate_mandelgrid(xmin, xmax, ymin, ymax, num_pixels, num_iters, max_val)    # spawn worker processes    workers = []    clients = []    for i in range(NUM_WORKERS):        workers.append( Process(target=worker_proc, args=(i, url_worker)) )        workers[i].start()    for i in range(NUM_CLIENTS):        clients.append( Process(target=client_proc, args=(url_client, i)) )        clients[i].start()    # Create queue with sockets    queue = LRUQueue(backend, frontend)    # Start reactor    # NOTE: starting an IOLoop should be done AFTER all process forking. One IOLoop per process. no sharing.    IOLoop.instance().start()    print("Program Closing")    sleep(1)    frontend.close()    backend.close()    print("sockets closed")    sleep(1)    context.term()    print("context terminated")    i = 1    for cli in clients:        print(f"Joining Client {i}")        cli.join()        i += 1    i = 1    for work in workers:        print(f"Joining Worker {i}")        # Hangs at joining first worker        work.join()        i += 1    print(f"NEVER REACHED HERE")    return 0if __name__ == "__main__":    main()

###################################################################################HERE IS THE OUTPUT WHEN I RUN IT:

$ python3 lbbroker3-mp.py/home/rpc/workspace/src/multibrot/lbbroker3-mp.py:2:VisibleDeprecationWarning: zmq.eventloop.minitornado is deprecated inpyzmq 14.0 and will be removed.Install tornado itself to use zmq with the tornado IOLoop.

from zmq.eventloop.ioloop import IOLoop Worker-0: HELLO Worker-2:HELLO num clients: 11 Worker-3: HELLO Worker-1: HELLO num clients: 10Client-0: OK Worker-0: HELLO num clients: 9 Client-1: OK Worker-2:HELLO num clients: 8 Client-2: OK num clients: 7 Worker-3: HELLOClient-3: OK Client-4: OK num clients: 6 num clients: 5 Worker-1:HELLO Worker-0: HELLO Client-5: OK num clients: 4 Worker-3: HELLOWorker-2: HELLO num clients: 3 num clients: 2 Client-6: OK Client-8:OK Client-7: OK num clients: 1 Client-10: OK Client-9: OK Worker-3:HELLO num clients: 0 Client-11: OK Program Closing sockets closedcontext terminated Joining Client 1 Joining Client 2 Joining Client 3Joining Client 4 Joining Client 5 Joining Client 6 Joining Client 7Joining Client 8 Joining Client 9 Joining Client 10 Joining Client 11Joining Client 12 Joining Worker 1

^CProcess Process-2: Process Process-4: Process Process-1: Traceback(most recent call last): File"/home/rpc/workspace/src/multibrot/lbbroker3-mp.py", line 182, inmain() File "/home/rpc/workspace/src/multibrot/lbbroker3-mp.py", line 174, in mainwork.join() File "/usr/lib/python3.10/multiprocessing/process.py", line 149, in joinres = self._popen.wait(timeout) File "/usr/lib/python3.10/multiprocessing/popen_fork.py", line 43, in waitTraceback (most recent call last):return self.poll(os.WNOHANG if timeout == 0.0 else 0) File "/usr/lib/python3.10/multiprocessing/popen_fork.py", line 27, in pollFile "/usr/lib/python3.10/multiprocessing/process.py", line 314, in_bootstrapself.run() File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in runself._target(*self._args, **self._kwargs) File "/home/rpc/workspace/src/multibrot/lbbroker3-mp.py", line 37, inworker_procaddress, empty, request = socket.recv_multipart() # This line is where File "/usr/lib/python3/dist-packages/zmq/sugar/socket.py",line 625, in recv_multipartparts = [self.recv(flags, copy=copy, track=track)] File "zmq/backend/cython/socket.pyx", line 781, inzmq.backend.cython.socket.Socket.recv File"zmq/backend/cython/socket.pyx", line 817, inzmq.backend.cython.socket.Socket.recvpid, sts = os.waitpid(self.pid, flag) File "zmq/backend/cython/socket.pyx", line 186, inzmq.backend.cython.socket._recv_copy File"zmq/backend/cython/checkrc.pxd", line 13, inzmq.backend.cython.checkrc._check_rc KeyboardInterruptKeyboardInterrupt Traceback (most recent call last): Traceback (mostrecent call last): File"/usr/lib/python3.10/multiprocessing/process.py", line 314, in_bootstrapself.run() File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in runself._target(*self._args, **self._kwargs) File "/home/rpc/workspace/src/multibrot/lbbroker3-mp.py", line 37, inworker_procaddress, empty, request = socket.recv_multipart() # This line is where File "/usr/lib/python3/dist-packages/zmq/sugar/socket.py",line 625, in recv_multipartparts = [self.recv(flags, copy=copy, track=track)] File "zmq/backend/cython/socket.pyx", line 781, inzmq.backend.cython.socket.Socket.recv File"zmq/backend/cython/socket.pyx", line 817, inzmq.backend.cython.socket.Socket.recv File"zmq/backend/cython/socket.pyx", line 186, inzmq.backend.cython.socket._recv_copy File"zmq/backend/cython/checkrc.pxd", line 13, inzmq.backend.cython.checkrc._check_rc File"/usr/lib/python3.10/multiprocessing/process.py", line 314, in_bootstrapself.run() File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in runself._target(*self._args, **self._kwargs) File "/home/rpc/workspace/src/multibrot/lbbroker3-mp.py", line 37, inworker_procaddress, empty, request = socket.recv_multipart() # This line is where KeyboardInterrupt File"/usr/lib/python3/dist-packages/zmq/sugar/socket.py", line 625, inrecv_multipartparts = [self.recv(flags, copy=copy, track=track)] File "zmq/backend/cython/socket.pyx", line 781, inzmq.backend.cython.socket.Socket.recv File"zmq/backend/cython/socket.pyx", line 817, inzmq.backend.cython.socket.Socket.recv File"zmq/backend/cython/socket.pyx", line 186, inzmq.backend.cython.socket._recv_copy File"zmq/backend/cython/checkrc.pxd", line 13, inzmq.backend.cython.checkrc._check_rc KeyboardInterrupt ProcessProcess-3: Traceback (most recent call last): File"/usr/lib/python3.10/multiprocessing/process.py", line 314, in_bootstrapself.run() File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in runself._target(*self._args, **self._kwargs) File "/home/rpc/workspace/src/multibrot/lbbroker3-mp.py", line 37, inworker_procaddress, empty, request = socket.recv_multipart() # This line is where File "/usr/lib/python3/dist-packages/zmq/sugar/socket.py",line 625, in recv_multipartparts = [self.recv(flags, copy=copy, track=track)] File "zmq/backend/cython/socket.pyx", line 781, inzmq.backend.cython.socket.Socket.recv File"zmq/backend/cython/socket.pyx", line 817, inzmq.backend.cython.socket.Socket.recv File"zmq/backend/cython/socket.pyx", line 186, inzmq.backend.cython.socket._recv_copy File"zmq/backend/cython/checkrc.pxd", line 13, inzmq.backend.cython.checkrc._check_rc KeyboardInterrupt


Viewing all articles
Browse latest Browse all 193

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>