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)