On 02/25/2016 03:57 PM, Alan Conway wrote:
I like this a lot.

The directional terms are still a problem. "source/sink" clashes with
AMQP "source/target". "inTreatment/outTreatment" is confusing because
"treatment" covers message and link treatments, but they don't always
flow in the same direction.  E.g.

     outTreatment: linkBalanced

"out" refers to *outbound* messages, but "linkBalanced" means balance
the *inbound* receiver link-open requests across external servers. This
made my head hurt.

"out" refers to the outbound leg of the route. In this case it means that messages flow out from the topic via links established by the consumers.


I have been fiddling around trying to find something genuinely better
but not there yet. I've got a couple of thoughts but not concrete yet:

  - separate message and link treatments in "treatment". This is clearer
but redundant and multiplies the number of in/out settings.

I think there's real value in having treatment be one-dimensional for simplifying the configuration.


  - if you need separate in/out treatments, split the waypoint into a
source/sink pair for the same address. That is less confusing because
the "half-route" only has one message flow direction so no need for
inFoo/outFoo. It makes the config a little more verbose but this is a
complex use case.

I prefer the second for clarity and future-proofing. It means we can
add future options that might be set differently for inbound/outbound
without multiplying inFoo/outFoo, inBar/outBar on the route.

This makes sense to me. It significantly reduces the number of attributes of a route and still keeps the most common cases simple.


On Wed, 2016-02-24 at 16:06 -0500, Ted Ross wrote:
Ok, how about this?

For direct messaging between producers and consumers:

Direct multicast delivery (one copy to every subscriber to the
address):

      route {
          address: service.mcast
          type: direct
          treatment: multicast
      }


Direct delivery to only the closest (lowest cost) subscriber:

      route {
          address: service.regional
          type: direct
          treatment: closest
      }


Direct delivery to one subscriber favoring subscribers that settle
deliveries more quickly.

      route {
          address: service
          type: direct
          treatment: balanced
      }


For messaging involving a queue, topic, or other intermediate
process.
In these cases, the remote container may be identified by container-
id
or connection label (container-id shown in examples):

Link-routing to a queue:

      route {
          address: my_queue
          type: waypoint
          treatment: linkBalanced
          container: <broker-container-id>
      }


Link-routing only for enqueue:

      route {
          address: my_queue
          type: sink
          treatment: linkBalanced
          container: <broker-container-id>
      }


Link-routing only for dequeue:

      route {
          address: my_queue
          type: source
          treatment: linkBalanced
          container: <broker-container-id>
      }


Simple queue waypoint (treatment defaults to 'balanced'):

      route {
          address: my_queue
          type: waypoint
          container: <broker-container-id>
      }


Simple topic waypoint that supports selectors:

      route {
          address: my_topic
          type: waypoint
          inTreatment: multicast
          outTreatment: linkBalanced
          container: <broker-container-id>
      }


Distributed (sharded) queue waypoint:

      route {
          address: my_queue
          type: waypoint
          container: <broker-1-container-id>
      }
      route {
          address: my_queue
          type: waypoint
          container: <broker-2-container-id>
      }


Distributed (sharded) topic waypoint:

      route {
          address: my_topic
          type: waypoint
          inTreatment: multicast
          outTreatment: linkBalanced
          container: <broker-1-container-id>
      }
      route {
          address: my_topic
          type: waypoint
          inTreatment: multicast
          outTreatment: linkBalanced
          container: <broker-2-container-id>
      }


=====================================================================
Syntax:

route: {
      type: direct | source | sink | waypoint
      address: (address or prefix)
      treatment: multicast | closest | balanced | linkBalanced
      connector: (label of a connection to/from a remote container)
      container: (ID of a connected remote container)
      inTreatment: (override treatment for inbound traffic)
      outTreatment: (override treatment for outbound traffic)
      inAddress: (override address for inbound traffic)
      outAddress: (override address for outbound traffic)
}


Some notes:

- I don't care for the negative connotations of "detour" and prefer
    "waypoint" for describing a thing you must go through on your way
to
    the final destination.
- I've replaced "fanout" + "bias" with "treatment" to describe how
the
    router handles the forwarding of messages.  There is precedent for
    the use of this term (hat tip to Andy Smith) in Cisco's router
    documentation.
- Link-routing is just another kind of treatment, like multicast or
    closest-consumer.  This removes the need for the "mixed" route as
    described by Gordon.  It also removes any distinction between a
    waypoint and a link-route-destination as a link-route-destination
    simply becomes a waypoint with linkBalanced treatment.
- I'm avoiding Alan's distinction between direct and indirect routes
by
    noting that "direct" is the only direct option whereas the other
    types are indirect.
- The notion of "direction" is replaced by the "source" and "sink"
    route types.


-Ted



On 02/24/2016 09:18 AM, Alan Conway wrote:
Minor update attached - I included Gordon's point about indirect
routes
being able to use a listener to accept an incoming broker
connection as
well as a connector to make an outgoing one, the new part:

----
Indirect routes can use incoming connections from the external
application by specifying a `listener` instead of a `connector` and
an
AMQP `container` name to identify the external application.

       indirectRoute {
           address: my_queue  # TODO address patterns.
           listener: secure_broker_listener
           container: "mybroker-container-id"
           mode="message"
       }
----

Here's the full thing:

===========
Terminology
===========

AMQP messages are sent on *links*. A link that sends messages from
an
application to a dispatch router is a *sender*. A link that
receives
messages for an application from a dispatch router is a *receiver*.

Dispatch router configuration defines *routes*. A route has an
*address*. Addresses can be AMQP address strings or patterns (TODO)

Incoming client links (senders or receivers) are attached to the
route
with a matching address. If a sender link has no address, messages
are
routed individually using the *to* address. Receiver links with no
address are not allowed.

There are several types of route:

A *directRoute* accepts sender and receiver links and forwards
messages
from senders to receivers. This allows clients to communicate
directly
without the need for a broker.

Example: direct route "foo" with fanout (replaces fixedAddress)

      "directRoute": { "address": "foo",  "fanout": "multiple" }

An *indirectRoute* creates links to an external application (such
as a
broker) and forwards messages from senders to the application, and
messages from the application to receivers. There are two modes:

   - message routing: the route creates its own links to the
external
application, there is no relationship with the sender/receiver
links.
   - link routing: the route creates external links that correspond
exactly with sender/receiver links. It forwards all link
information
(name, flow control, properties etc.) to the external application.

Link routing preserves more AMQP context between the client and the
external application. Message routing offers more flexibility to
modify
the message flow e.g. to load balance messages over multiple
brokers.

An indirectRoute can initiate a connection to the external
application
or accept an incoming connection from it.

Example: broker integration with link routing (replaces
linkRoutePattern)

       indirectRoute {
           address: my_queue  # TODO address patterns.
           connector: my_broker
           mode="link"
       }

Example: broker integration with message routing (replaces simple
waypoint)

       indirectRoute {
           address: my_queue  # TODO address patterns.
           connector: my_broker
           mode="message"
       }

Indirect routes can use incoming connections from the external
application by specifying a `listener` instead of a `connector` and
an
AMQP `container` name to identify the external application.

       indirectRoute {
           address: my_queue  # TODO address patterns.
           listener: secure_broker_listener
           container: "mybroker-container-id"
           mode="message"
       }

For more complex cases routes can create links to other routes.
Routes
always allow internal links, but a route can be configured to allow
only senders, receivers, both or none from outside. An external
link is
attached to the route that has the right its address *and* allows
that
link type. A route with `"allow": "none"` is an internal routing
detail
and cannot be accessed directly by clients.

Example: waypoint chaining

       # Route for messages sent to my_queue, forward to broker1
       indirectRoute {
           address: my_queue
           allow: sender
           connector: broker1
           mode: message
       }

       # Internal route for messages coming back from broker1,
forward to
broker2
       indirectRoute {
           address: my_queue
           allow: none  # internal only
           connector: broker1
           internalSender: ["broker2"] # send to broker2
           mode: message
      }

       # Route messages through broker2 and then back to receivers.
       indirectRoute {
           internalAddress: "broker2"
           connector: broker2
           allow: receiver
           mode: message
       }

Example: message-routing with load balancing over two brokers.

       # Route for senders to my_queue.
       directRoute {
           address: my_queue
           allow: sender
           internalSenders: ["broker1_my_queue", "broker2_my_queue"]
           fanout: multiple
       }

       # Route for receivers from my_queue.
       directRoute {
           address: my_queue
           allow: receiver
           internalReceivers: ["broker1_my_queue",
"broker2_my_queue"]
       }

       # Internal route to broker1
       indirectRoute {
           internalAddress: broker1_my_queue
           allow: none
           connector: broker1
       }

       # Internal route to broker2
       indirectRoute {
           internalAddress: broker2_my_queue
           allow: none
           connector: broker2
       }

TODO:

- indirect route with multiple listeners/connectors with/without
container name giving multiple choices of external apps. Policy
controol: link routes can't fan-out but they can load balance.
- mix link & message routes: "tap" messages from a link route and
message route them.
- pattern matching
- internal address rewriting?
- multi-tennant




-----------------------------------------------------------------
----
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to