1

I am implementing a consensus algorithm (raft) where 5 servers have to communicate together asynchronously to manage a replicated log. I am using python and multiprocessing package to run 5 processes acting as servers, and ØMQ (pyzmq) to handle communications between servers.

I drafted a first design and I am wondering about a few things:

I have 5 servers, and I hardcode 5 "identities" I configure sockets with. For each server, I am using two ROUTER sockets:

  • the first one is binding to the server's identity (this socket is responsible for receiving others messages)
  • the other one is connecting to the other servers' identities (this one is responsible for sending messages)

It looks strange to me to use two ROUTER sockets on the same node/server, but I do not find better : is there a more elegant way to proceed?

I tried to use only one ROUTER socket per server, i.e a socket that sets its identity, binds on its given port, and connects to the others, but this 'connect' step on each side doesn't work : what is the reason for that?

Here is a simple example with 3 servers:

import time
from threading import Thread
from typing import List

import zmq

SEND_RULE = {
    '5555': '6666',
    '6666': '7777',
    '7777': '5555'
}

def worker(socket_port: str, peer_ports: List[str]):
    context = zmq.Context()

    receiving_socket = context.socket(zmq.ROUTER)
    receiving_socket.setsockopt(zmq.IDENTITY, socket_port.encode())
    receiving_socket.bind(f'tcp://*:{socket_port}')

    sending_socket = context.socket(zmq.ROUTER)
    sending_socket.setsockopt(zmq.IDENTITY, socket_port.encode())

    for peer_port in peer_ports:
        sending_socket.connect(f'tcp://localhost:{peer_port}')

    time.sleep(1)

    recipient_id = SEND_RULE[socket_port].encode()
    message_for_recipient = b'coucou!'

    print(socket_port, ' sending a message to ', recipient_id.decode())
    sending_socket.send_multipart([recipient_id, message_for_recipient])

    # Receive a message from peer
    sender_id, sender_message = receiving_socket.recv_multipart()

    print( socket_port,
         ' server received: ',
           sender_message.decode(),
         ' from: ',
           sender_id.decode()
           )


if __name__ == '__main__':
    socket_ports = ['5555', '6666', '7777']
    for socket_port in socket_ports:
        Thread( target = worker,
                args   = ( socket_port,
                           [ port for port in socket_ports
                                   if port != socket_ports ]
                           )
                ).start()

    time.sleep(3)

user3666197
  • 1
  • 6
  • 50
  • 92
joubs
  • 123
  • 8
  • And the MCVE-code is where? – user3666197 May 06 '20 at 12:11
  • Rudely asked, but here it is! – joubs May 06 '20 at 14:11
  • StackOverflow strongly discourages Community Members from not following the Community Rules & Best Practices - one of which is not to present an MCVE-code formulation of the problem a Member is asking the Community to sponsor a help with. Posting a Question without any MCVE-code formulated problem is both meaningless w.r.t. the subject and arrogant w.r.t. the Community Ethics. **Feel free to violate the Community Rules as much as you wish**, yet the only results achieved by doing so are going sort of against initial your wish to receive from us a sponsored help with your problem, aren't they? – user3666197 May 06 '20 at 15:27
  • From https://stackoverflow.com/help/how-to-ask : "Not all questions benefit from including code." I sincerely considered my description contained enough information, but I can, of course, hear that it needs more details : asking a nice way seems sensible then. Thank you for your edit. – joubs May 06 '20 at 16:26

0 Answers0