java - ZeroMQ: Disappearing messages -
we have java application acting server. client applications (written in c#) communicating using zeromq. (mostly) following lazy pirate pattern.
the server has router socket, implemented follows (using jeromq):
zcontext context = new zcontext(); socket socket = context.createsocket(zmq.router); socket.bind("tcp://*:5555");
the clients connect , send messages this:
zcontext context = zcontext.create(); zsocket socket = zsocket.create(context, zsockettype.req); socket.identity = encoding.utf8.getbytes("some identity"); socket.connect("tcp://my_host:5555"); socket.send(new zframe("request data"));
we have experienced lost messages when multiple clients sending messages @ same time. single client, there doesn't appear problem.
are implementing right way multiple-client-single-server setup?
update: example client , server exhibiting behaviour:
server:
import org.zeromq.zcontext; import org.zeromq.zmq; import org.zeromq.zmq.pollitem; import org.zeromq.zmq.poller; import org.zeromq.zmq.socket; import org.zeromq.zmsg; public class simpleserver { public static void main(string[] args) throws interruptedexception { zcontext context = new zcontext(); socket socket = context.createsocket(zmq.router); socket.setroutermandatory(true); socket.bind("tcp://*:5559"); pollitem pollitem = new pollitem(socket, poller.pollin); int messagesreceived = 0; int pollcount = 0; while ((pollcount = zmq.poll(new pollitem[]{pollitem}, 3000)) > -1) { messagesreceived += pollcount; (int = 0 ; < pollcount ; i++) { zmsg msg = zmsg.recvmsg(socket); system.out.println(string.format("received message: %s. total messages received: %d", msg, messagesreceived)); } if (pollcount == 0) { system.out.println(string.format("no messages on socket. total messages received: %d", messagesreceived)); } } } }
client:
using netmq; using system; using system.text; namespace simpleclient { class program { static byte[] identity = encoding.utf8.getbytes("id" + datetime.utcnow.ticks); static void main(string[] args) { (int = 0; < 100; i++) { sendmessage(); } } private static void sendmessage() { using (netmqcontext context = netmqcontext.create()) { using (netmqsocket socket = context.createrequestsocket()) { socket.options.identity = identity; socket.connect("tcp://localhost:5559"); socket.send(encoding.utf8.getbytes("hello!")); } } } } }
if run server , single client, can see 100 messages arrive. if run, say, 5 clients simultaneously, around 200 -> 300 messages arrive, instead of full 500. aside, appears closing socket in client somehow stopping router socket on server receiving messages briefly, although theory.
part 1 - poll may return more 1 event
zmq.poll()
returns number of events found:
int rc = zmq.poll(new pollitem[]{pollitem}, 3000);
you assume 1 return poll
1 event. instead, should loop on zmsg msg = zmsg.recvmsg(socket);
number of events indicated return of zmq.poll()
.
/** * polling on items. has poor performance. * try use zmq_poll selector * caution: affected jdk epoll bug * * @param items * @param timeout * @return number of events */ public static int zmq_poll(pollitem[] items, long timeout) { return zmq_poll(items, items.length, timeout); }
part 2 - zmsg.receive() may return multiple frames
when receive zmsg
zmsg msg = zmsg.recvmsg(socket);
, zmsg
may contain multiple zframe
s, each containing client data.
from comments of zmsg
class in jeromq's source:
* // receive message zmqsocket "input" socket object , iterate on frames * zmsg receivedmessage = zmsg.recvmsg(input); * (zframe f : receivedmessage) { * // frame f (of type zframe) * }
part 3 - messages can split across multiple zframes
from zframe's source in jeromq:
* zframe class provides methods send , receive single message * frames across 0mq sockets. 'frame' corresponds 1 underlying zmq_msg_t in libzmq code. * when read frame socket, more() method indicates if frame part of * unfinished multipart message.
if i'm understanding correctly, each event may multiple frames, , 1 client message may map 1..n frames (if message big?).
so summarize:
- one return poll may indicate multiple events.
- one event , 1
zmsg.receive()
may contain multiple frames - one frame contain 1 complete client message or part of client message; 1 client message maps 1..n frames.
Comments
Post a Comment