qpid-proton mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Rafael Schloming <...@alum.mit.edu>
Subject Re: What are the use cases for pn_transport_unbind?
Date Thu, 04 Apr 2013 12:13:06 GMT
On Thu, Apr 4, 2013 at 5:01 AM, Keith W <keith.wall@gmail.com> wrote:

> I'm curious to understand the use-cases for the pn_transport_unbind API
> method.
> I understand that one such use case is failover.  When a client
> discovers that it has lost connectivity to the server, the client
> calls pn_transport_unbind to unbind the connection from the old
> transport, establish a new socket and new transport and use
> pn_transport_bind to bind to original connection to the new transport,
> thus re-establishing state on the server.  In this scenario,
> pn_transport_unbind is not used server-side.  Is this correct?

Yes, FWIW I've never actually tried to use it for a full failover scenario.
Messenger currently uses unbind for redirect scenarios which you can
effectively think of as a subset of the full connection failover scenario.

> Are there other use-cases where the use of pn_transport_unbind is
> anticipated?

I don't know offhand, however I wouldn't say unbind is there purely to
support failover. It's really part of the general resource model around
transports and connections. The transport keeps state associated with a
physical tcp connection. When that goes away, you don't necessarily need or
want to keep all that state around, however if you are coding for recovery
then you will want to keep the Connection around and examine the last known
state of all its deliveries. Unbind lets you break the association between
the top and bottom half and therefore handle the cleanup around each part
separately. Hypothetically you might be able to clean up the transport
first and reclaim resources sooner, but really I'd say the point is to be
able to handle the top half/bottom half cleanup in separate places in your
application. It's much more natural to cleanup the bottom half closer to
your network code, and clean up the top half somewhere else in the
application logic.

It might help to understand how bind came about in the first place. Prior
to the existence of bind, there was no way to process bytes without fully
creating both the top half and the bottom half. This forced the
creation/configuration of the top half at a very low level place in the
code, i.e. the instant you accept a TCP connection. Unfortunately where you
accept the tcp connection you don't necessarily have enough information to
create/configure the top half the way you wanted to, so you're forced to
either pull application logic into what should be pure network code, or
delay creation of the top/bottom half and therefore delay your ability to
process any bytes. By decoupling the lifecycle of the top/bottom half you
can now create the bottom half where it is natural to do so, and the bottom
half can instantly start enforcing heartbeats, idle timeouts etc. This
makes the engine much more robust to certain DoS scenarios, and also allows
the transport to offer up information to the application that it might find
useful in creating the top half, e.g. the transport can inform the app if
the authentication succeeded or failed, or who the user is, etc, and the
app can use this information to decide how to create/configure the top half.

The fact that you happen to be able to use this to achieve a certain style
of failover is really simply an artifact of the overall design, however I
certainly wouldn't think of it as *the* intended use case for unbind.
Really unbind is just the compliment to bind. Bind allows you to decouple
creation/setup of the top/bottom half, and unbind allows you to decouple
their cleanup/destruction.

> It occurs to me that in a peer to peer use-case it would be
> problematic if both peers were to use pn_transport_unbind/bind when
> trying to re-establish communication following a connectivity issue as
> both sides would try to _actively_ re-initiate each session (having
> the effect of doubling the number of sessions) and then each peer
> would try and reattach the links on its initiated session.  Is this
> correct? Or does the system have additional behaviour to prevent this?

 There is no behaviour to prevent this. I think failover for something
acting in a server role (whether it's a broker or a peer) is always going
to require a bit more than just a simple bind/unbind. I think in your case
the peer acting as the server would need to close all the old sessions and
then wait for the other peer to initiate and migrate the links over to the
new sessions. If this turned out to be common/useful we could probably do
something to make it convenient or possibly even automatic to perform this
kind of link migration within the same connection, however at this point I
wouldn't rate it as super high priority scenario.

FWIW, I think even for a simple interface like messenger a complete
failover solution wouldn't based solely on bind/unbind. The simple
bind/unbind strategy is really doing connection oriented failover, and with
a message-oriented client, it's more natural to think of failover in terms
of routing, e.g. you can imagine the ability to supply routing rules that
specify multiple "next hops" for addresses matching a given pattern, and if
you lose connectivity to one or more of your "next hops", then you route
the messages to one of the backups depending on the level of QoS specified
on the message. While you might still use bind/unbind in this strategy, you
wouldn't simply be blindly attempting to recover the whole connection,
you'd have to go through and settle all the deliveries that didn't have the
appropriate QoS level, and depending on the code structure I can see how it
might just be easier to construct a new top half rather than trying to
reuse the old one.

So to summarize, I would say bind/unbind are really about decoupling the
lifecycles of the top and bottom half. This certainly can play a role in
failover since the general process of failover involves the active partner
taking the top half from a failed connection and somehow transforming that
into zero or more top halves for use with new transports, and of course the
strategies for transformation could include:

  - throwing it away (i.e. not failing over)
  - reusing it directly
  - modifying it
  - constructing an exact replica
  - constructing a modified replica
  - constructing 2 or 3 new top halves which carry different parts of the
key state from the original

In all of these cases unbind followed by a bind are part of the process,
though not necessarily on the same object(s).


  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message