[zeromq-dev] ZMQ reconnect/ephemeral ports
Luca Boccassi
luca.boccassi at gmail.com
Sat Sep 2 19:21:44 CEST 2017
On Sat, 2017-09-02 at 12:02 -0400, Bill Torpey wrote:
> Thanks again, Luca!
>
> For now, I’m going to go with disabling reconnect on the “data”
> sockets — that seems to be the best solution for my use case
> (connecting to endpoints that were returned by the peer binding to an
> unspecified (“wildcard”) port — e.g., "tcp://<interface>:*" in ZMQ).
>
> This assumes that ZMQ will completely forget about the endpoint
> if/when it is disconnected, if it is set not to reconnect. Otherwise
> I might run afoul of ZMQ’s silently ignoring connections to endpoints
> that it already knows about: https://github.com/zeromq/libzmq/issues
> /788 <https://github.com/zeromq/libzmq/issues/788> (e.g., in the case
> where another process later happens to be assigned the same ephemeral
> port).
>
> I’ve done a quick scan of the libzmq code (v4.2.2) and it doesn’t
> appear that the endpoint is removed in the case of a (terminal)
> disconnect. If you can confirm/deny this behavior, that would be
> helpful. Failing that, I guess I’ll need to test this in the
> debugger — any hints on how best to do this would also be much
> appreciated.
>
> Regards,
>
> Bill
Yes it doesn't look like it removes the endpoint - I guess it's a
corner case that's missed. I'll open an issue.
BTW all these things are very quick and easy to try with Python on
Linux. Just install pyzmq, open a python3 terminal and:
import zmq
ctx = zmq.Context.instance()
rep = ctx.socket(zmq.REP)
rep.bind("tcp://127.0.0.1:12345")
req = ctx.socket(zmq.REQ)
req.connect("tcp://127.0.0.1:12345")
req.send_string("hello")
rep.recv()
rep.send_string("hallo")
req.recv()
rep.unbind("tcp://127.0.0.1:12345")
rep.close()
rep = ctx.socket(zmq.REP)
rep.bind("tcp://127.0.0.1:12345")
req.send_string("hello")
rep.recv()
rep.send_string("hallo")
req.recv()
rep.unbind("tcp://127.0.0.1:12345")
rep.close()
req.close()
rep = ctx.socket(zmq.REP)
rep.bind("tcp://127.0.0.1:12345")
req = ctx.socket(zmq.REQ)
req.setsockopt(zmq.RECONNECT_IVL, -1)req.connect("tcp://127.0.0.1:12345")
req.send_string("hello")
rep.recv()
rep.send_string("hallo")
req.recv()
rep.unbind("tcp://127.0.0.1:12345")
rep.close()
rep = ctx.socket(zmq.REP)
rep.bind("tcp://127.0.0.1:12345")
req.send_string("hello")
rep.recv()
This last one won't receive the message
> > On Sep 1, 2017, at 6:19 PM, Luca Boccassi <luca.boccassi at gmail.com>
> > wrote:
> >
> > On Fri, 2017-09-01 at 18:03 -0400, Bill Torpey wrote:
> > > Thanks Luca! That was very helpful.
> > >
> > > Although it leads to a couple of other questions:
> > >
> > > - Can I assume that a ZMQ disconnect of a tcp endpoint would only
> > > occur if the underlying TCP socket is closed by the OS? Or are
> > > there
> > > conditions in which ZMQ will proactively disconnect the TCP
> > > socket
> > > and try to reconnect?
> >
> > Normally that's the case - you can set up heartbeating with the
> > appropriate options and that will kill a connection if there's no
> > answer
> >
> > > - I see that there is a sockopt (ZMQ_RECONNECT_IVL) that can be
> > > set
> > > to -1 to disable reconnection entirely. In my case, the the
> > > “data”
> > > socket pair will *always* connect to an ephemeral port, so I
> > > *never*
> > > want to reconnect. Would this be a reasonable option in my case,
> > > do
> > > you think?
> >
> > If that makes sense for your application, go for it - in these
> > cases
> > the only way to be sure is to test it and see how it works
> >
> > > - Would there be any interest in a patch that would disable
> > > reconnects (controlled by sockopt) for ephemeral ports only? I’m
> > > guessing that reconnecting mostly makes sense with well-known
> > > ports,
> > > so something like this may be of general interest?
> >
> > If by ephemeral port you mean anything over 1024, then actually in
> > most
> > applications I've seen it's always useful to reconnect, and the
> > existing option should be enough for those cases where it's not
> > desired
> > - we don't want to duplicate functionality
> >
> > > Thanks again!
> > >
> > > Bill
> > >
> > > > On Sep 1, 2017, at 5:30 PM, Luca Boccassi <luca.boccassi at gmail.
> > > > com>
> > > > wrote:
> > > >
> > > > On Fri, 2017-09-01 at 16:59 -0400, Bill Torpey wrote:
> > > > > I'm curious about how ZMQ handles re-connection. I
> > > > > understand
> > > > > that
> > > > > re-connection is supposed to happen "automagically" under the
> > > > > covers,
> > > > > but that poses an interesting question.
> > > > >
> > > > > To make a long story short, the application I'm working on
> > > > > uses
> > > > > pub/sub sockets over TCP. and works like follows:
> > > > >
> > > > > At startup:
> > > > > 1. connects to a proxy/broker at a well-known address, using
> > > > > a
> > > > > pub/sub socket pair ("discovery");
> > > > > 2. subscribes to a well-known topic using the "discovery"
> > > > > sub
> > > > > socket;
> > > > > 3. binds a different pub/sub socket pair ("data") and
> > > > > retrieves
> > > > > the
> > > > > actual endpoints assigned;
> > > > > 4. publishes the "data" endpoints from step 3 on the
> > > > > "discovery"
> > > > > pub
> > > > > socket;
> > > > >
> > > > > When the application receives a message on the "discovery"
> > > > > sub
> > > > > socket, it connects the "data" socket pair to the endpoints
> > > > > specified
> > > > > in the "discovery" message.
> > > > >
> > > > > So far, this seems to be working relatively well, and allows
> > > > > the
> > > > > high-volume, low-latency "data" messages to be sent/received
> > > > > directly
> > > > > between peers, avoiding the extra hop caused by a
> > > > > proxy/broker
> > > > > connection. The discovery messages use the proxy/broker, but
> > > > > since
> > > > > these are (very) low-volume the extra hop doesn't
> > > > > matter. The
> > > > > use of
> > > > > the proxy also eliminates the "slow joiner" problem that can
> > > > > happen
> > > > > with other configurations.
> > > > >
> > > > > My question is what happens when one of the "data" peer
> > > > > sockets
> > > > > disconnects. Since ZMQ (apparently) keeps trying to
> > > > > reconnect,
> > > > > what
> > > > > would prevent another process from binding to the same
> > > > > ephemeral
> > > > > port?
> > > > >
> > > > > - Can I assume that if the new application at that port is
> > > > > not a
> > > > > ZMQ
> > > > > application, that the reconnect will (silently) fail, and
> > > > > continue to
> > > > > be retried?
> > > >
> > > > The ZMTP handshake would fail, so yes.
> > > >
> > > > > - What if the new application at that port *IS* a ZMQ
> > > > > application? Would the reconnect succeed? And if so, what
> > > > > would
> > > > > happen if it's a *DIFFERENT* ZMQ application, and the
> > > > > messages
> > > > > that
> > > > > it's sending/receiving don't match what the original
> > > > > application
> > > > > expects?
> > > >
> > > > Depends on how you handle it in your application. If you have
> > > > security
> > > > concerns, then use CURVE with authentication so that only
> > > > authorised
> > > > peers can connect.
> > > >
> > > > > It's reasonable for the application to publish a disconnect
> > > > > message
> > > > > when it terminates normally, and the connected peers can
> > > > > disconnect
> > > > > that endpoint. But, applications don't always terminate
> > > > > normally
> > > > > ;-)
> > > >
> > > > That's a common pattern. But the application needs to handle
> > > > unexpected
> > > > data somewhat gracefully. What that means is entirely up to the
> > > > application - as far as the library is concerned, if the
> > > > handshake
> > > > succeeds then it's all good (hence the use case for CURVE).
> > > >
> > > > > Any guidance, hints or tips would be much appreciated --
> > > > > thanks
> > > > > in
> > > > > advance!
> > > >
> > > > --
> > > > Kind regards,
> > > > Luca Boccassi_______________________________________________
> > > > zeromq-dev mailing list
> > > > zeromq-dev at lists.zeromq.org <mailto:zeromq-dev at lists.zeromq.org
> > > > > <mailto:zeromq-dev at lists.zeromq.org <mailto:zeromq-dev at lists.
> > > > zeromq.org>>
> > > > https://lists.zeromq.org/mailman/listinfo/zeromq-dev
> > > > <https://lists.zeromq.org/mailman/listinfo/zeromq-dev>
> > > > <https://lists.zeromq.org/mailman/listinfo/zeromq-dev
> > > > <https://lists.zeromq.org/mailman/listinfo/zeromq-dev>>
> > >
> > > _______________________________________________
> > > zeromq-dev mailing list
> > > zeromq-dev at lists.zeromq.org <mailto:zeromq-dev at lists.zeromq.org>
> > > https://lists.zeromq.org/mailman/listinfo/zeromq-dev
> > > <https://lists.zeromq.org/mailman/listinfo/zeromq-dev>
> >
> > --
> > Kind regards,
> > Luca Boccassi_______________________________________________
> > zeromq-dev mailing list
> > zeromq-dev at lists.zeromq.org <mailto:zeromq-dev at lists.zeromq.org>
> > https://lists.zeromq.org/mailman/listinfo/zeromq-dev
> > <https://lists.zeromq.org/mailman/listinfo/zeromq-dev>
>
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> https://lists.zeromq.org/mailman/listinfo/zeromq-dev
--
Kind regards,
Luca Boccassi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20170902/5ccecb0f/attachment.sig>
More information about the zeromq-dev
mailing list