Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proxy of PULL-->ROUTER for solving the load-balancing pattern? #4704

Open
javiabellan opened this issue Jul 12, 2024 · 0 comments
Open

proxy of PULL-->ROUTER for solving the load-balancing pattern? #4704

javiabellan opened this issue Jul 12, 2024 · 0 comments

Comments

@javiabellan
Copy link

I want to implement in zeroMQ something similar to this:

esquema_async

Where:

  • N user queues (PUSH --> PULL ) sends messages to the common queue (proxy frontent endpoint) in a Round Robin way (ZeroMQ push-pull pattern already handle this).
  • Proxy (PULL --> ROUTER) fowards messages from PULL socket (frontend) to ROUTER socket (backend)
  • N workers (REQ sockets) ask for tasks to the proxy ROUTER (backend) endpoint, whenever they free from their previus task (Load Balancing pattern).

Current solution

Currently i solve the proxy with the following (python) code

import zmq

context = zmq.Context()

# Socket to receive messages from clients
frontend = context.socket(zmq.PULL)
frontend.bind("tcp://*:5555")

# Socket to handle worker requests and send tasks
backend = context.socket(zmq.ROUTER)
backend.bind("tcp://*:5556")

# Poller to multiplex the sockets
# (Listen from both sockets simultanesolly)
poller = zmq.Poller()
poller.register(frontend, zmq.POLLIN)
poller.register(backend, zmq.POLLIN)

# Manually code to handle the load balancing pattern !!!
available_tasks   = []
available_workers = []

while True:

    socks = dict(poller.poll())

    # New task arrives
    if socks.get(frontend) == zmq.POLLIN:
        task = frontend.recv_string()
        available_tasks.append(task)

    # New worker sends the "im free" notification
    if socks.get(backend) == zmq.POLLIN:
        message = backend.recv_multipart()
        worker_id = message[0]
        _ = message[1]  # The empty frame
        worker_request = message[2]
        available_workers.append(worker_id)

    if available_tasks and available_workers:
        # Send the next task to the requesting worker
        task      = available_tasks.pop(0)
        worker_id = available_workers.pop(0)
        backend.send_multipart([worker_id, b'', task.encode()])

# Clean up
frontend.close()
backend.close()
context.term()

Idea:

Make Load Balancing code part of the ZeroMQ library to save code. Maybe the Proxy zeroMQ API could be a good interface for that:

import zmq

context = zmq.Context()

# Set up the frontend (PULL socket)
frontend = context.socket(zmq.PULL)
frontend.bind("tcp://*:5555")

# Set up the backend (ROUTER socket)
backend = context.socket(zmq.ROUTER)
backend.bind("tcp://*:5556")

try:
    zmq.proxy(frontend, backend)
except KeyboardInterrupt:
    print("W: interrupt received, stopping…")

# Clean up
frontend.close()
backend.close()
context.term()

I'm new to the zeroMQ library and probably i am missing something, but after reading the guide (ch 3, the load-balancing pattern) i found that manual code is needed to handle this type of pattern.

@javiabellan javiabellan changed the title proxy of PULL-->ROUTER ? proxy of PULL-->ROUTER for solving the load-balancing pattern? Jul 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant