More comments inline below with some snippage.

On 28/02/14 19:51, Rob Godfrey wrote:
On 28 February 2014 19:36, Fraser Adams <[email protected]>wrote:

Funnily enough my "mental model" of AMQP 0.10 in an AMQP 1.0 context has
tended to be as above with bindings as "internal links".

Though it's probably not as clear-cut as that. For sure if a producer is
sending to an exchange (as an addressable node) and a consumer is receiving
from a queue (as an addressable node) and we've established some bindings
administratively then creating said bindings is pretty close to
establishing an internal link, However if one has a consumer receiving from
an exchange as an addressable node it gets more interesting in that case
although we have a queue created (in physical terms) that queue is really
an artefact of the subscription and is (I think) actually a source terminus
associated to the exchange node and one or more links.

That's all quite "exciting" because the same physical things on the broker
are semantically a little different depending on how things were
established, which messes with my head a bit :-D don't know whether it's
possible (or whether you'd want to) distinguish between the two different
scenarios in a Management Model??



So to me, if you allow subscriptions to an exchange then you should present
to the management user the same view that the application is getting (i.e.
the fact that a queue object has been created to provide buffering is an
implementation detail).
Hmm "kind of", so I'd be content that this was a different type of queue than a queue node, but the information is still pretty useful.

We've discussed some time ago that my core use case is perhaps a little different than ones that your customers tend to use but mine involves real-time very high rate producers, and consumers that need to scale out and select messages based on their properties, so my subscriptions tend to: 1) Be "shared" subscriptions - so I can have multiple physical consumer hosts receiving from a given subscription queue (i.e. they may be viewed as the same logical consumer scaled out across several physical instances over multiple hosts). 2) The subscription queues don't (generally) need to be durable, though they are in a couple of cases. 3) I absolutely need ring/circular queues because my producers are real time and I can't slow down time if a consumer happens to fail :-) 4) I can't just simply throw away messages entirely if a consumer fails either - so I have "topic like" behaviour, but also a need to give a little leeway in case the consumer failure is transient (I tend to use queues around 2GB) if the consumer is down and stays down messages get overwritten because of the circular queue, but if the consumer comes back before that happens it can catch up. That's another reason for the shared subscription queues 'cause consumers can scale out to recover from a backlog.

All of that stuff is possible in AMQP 0.10 exchange/binding/queue model and is also possible in AMQP 1.0 (in qpidd at anyrate) using shared subscription queues (e.g. with node: {capabilities: [shared]}) and using Gordon's "topic" pseudo-node as a mechanism to configure subscription queues created by topic-like nodes (this is how I create my ring queues) e.g.

qpid-config add topic topic --argument exchange=amq.match \
--argument qpid.max_size=2000000000 --argument qpid.policy_type=ring


At the moment when I do all of that stuff in qpidd it *looks* like I end up with an exchange node, a queue node and bindings between them, though in practice as I say I think that the queue is semantically not *really* a queue node and might be better as something else (perhaps as I said earlier a source terminus associated with the exchange).

However from my perspective recording it the way that it's currently done is actually pretty useful because I like to be able to see the subscription queues and I also like to be able to determine what's connecting to them (and/or be able to find any subscription queues associated with a connection).


  I think ultimately in the Java Broker I would like
to allow consumers to link to things that look a lot like exchanges,
however I think the behaviour might be slightly different.  To me an
exchange is an instance of a class of nodes which passes messages from an
incoming link to an outgoing link without ever taking responsibility for
the message (or providing any buffering/storage).
Hmmm I think this is a little bit of a grey area. You are probably right to say what you are saying above, but without associated storage the pub/sub model breaks down a little because you generally want to be decoupling publishers from subscribers and without queues it's hard to decouple.

To my mind what you are describing above feels more like the sort of behaviour of a router than a broker.

That said, I sort of agree with what you are saying from a philosophical level, that's one of the reasons that I quite like Gordon's "topic" pseudo-node concept, so in that case you're describing something that looks a lot like an exchange, but allows subscription queues to have a particular configuration.


  A queue is an instance
of the class of nodes that does take responsibility for a message (and - as
it happens - also provides storage).  A link may or may not provide
buffering / storage (links between containers will always have to provide
buffering...
Is it the link or is it the terminus? I'm clearly not as much of an AMQP 1.0 expert as you are, but I thought that a link multiplicity was 0..1 at each end (from the perspective of the link) so for the concept of shared subscriptions to be possible the storage is *really* in the source terminus rather than the link if you are considering subscription queues.

internal links may or may not provide buffering - currently
the Java Broker models message flows across bindings as a synchronous
operation) but never itself takes responsibilitiy.  So, to my mind I feel
that an exchange with subscriptions should either insist that all messages
sent to it are sent unreliably (pre-settled), or it should only settle when
consumers have taken the message and taken responsibility themselves.  This
is somewhat different from the 0-x exchange behaviour where the broker
takes responsibility for the message (because it actually places the
message in one or more queues).

As I say above I'd kind of agree with this from a purist/philosophical perspective, but again as I say about this feels somewhat more router-like behaviour than broker like.

At the moment (in qpidd at least) the default behaviour when subscribing to an exchange is for a temporary queue to get created, I guess I'd be reasonably agnostic about a move to a model like you are suggesting above *as long as* I've still got the ability to execute my core use case above - if we call things that allow such behaviour topics rather than exchanges then I really don't mind, but I really *do mind* if I can't execute my core use case!!


From my perspective I think Gordon has done a brilliant job providing AMQP 1.0 mappings and mechanisms for this sort of complex use case and I for one want to publicly thank him!! I've not had a chance yet to see if similar mechanisms exist in the Java Broker, though I'd expect some differences even if roughly equivalent /mechanisms/ exist.

It's surprisingly complex, though perhaps I shouldn't be surprised given how little AMQP 1.0 actually mandates.

Yes - I think we'd need to start out simple... all queues have names...
right? and then see what aspects we think are common, which should be
factored and where we currently have different ways of doing things trying
to decide whether there is a common abstraction which we can use to
describe across both instances (and in Dispatch and Messenger too).  In
general I feel there is probably more in common with stuff that both
brokers are capable of than there is different...
So the general philosophy of what you are saying I don't dispute, the point that I was making was that there is currently some baggage around even this simple stuff in both QMF and the Java Broker model - at a trivial level whose name do we pick? Are you willing to change property names? Are the QMF guys? It's not *technically* hard for sure, but it does need a fairly grown-up attitude and a shared desire, so probably needs good leadership on the part of the Java and C++ camps to get that sort of alignment.

  However there will also
be large amounts of functionality that is specific to one broker or the
other... and that is fine.  Where the other side has an interest we should
discuss the naming / semantics... and maybe aspire to implement at some
later date... But as long as we keep things in bite-sizd chunks and not try
to say that every queue has to implement all these bazillion features, then
I don't think it will necessarily be as hard as you might think.

As above I largely agree that it's not *technically* too hard, it's more that the community has to buy in and engage with the spirit of trying to align as much as is sensible and perhaps to accept that some much-loved property names will get changed for the common good.


So one of my issues with QMF is that schema and mechanism weren't as
cleanly separated as I'd like.  The ability to perform the CRUD operations
appears to be a property of Broker objects rather than something generic...
Perhaps, but if you look at QMF Broker Management Objects in another way they are actually pretty darned close to the behaviour of and AMQP 1.0 Management Node albeit with a few Manageable Entity properties thrown in.

    <method name="create" desc="Create an object of the specified type">
<arg name="type" dir="I" type="sstr" desc="The type of object to create"/> <arg name="name" dir="I" type="sstr" desc="The name of the object to create"/> <arg name="properties" dir="I" type="map" desc="Type specific object properties"/> <arg name="strict" dir="I" type="bool" desc="If specified, treat unrecognised object properties as an error"/>
    </method>

    <method name="delete" desc="Delete an object of the specified type">
<arg name="type" dir="I" type="sstr" desc="The type of object to delete"/> <arg name="name" dir="I" type="sstr" desc="The name of the object to delete"/> <arg name="options" dir="I" type="map" desc="Type specific object options for deletion"/>
    </method>

    <method name="query" desc="Query the current state of an object.">
<arg name="type" dir="I" type="sstr" desc="The type of object to query."/> <arg name="name" dir="I" type="sstr" desc="The name of the object to query"/> <arg name="results" dir="O" type="map" desc="A snapshot of the object's state."/>
    </method>

So you do say:

create(name, type, properties)

Which is pretty darned like section 5.2 where you talk to $management and pass
application-properties:
name->newQueue
operation->CREATE
type->org.example.queue

application-data:
A map of properties pretty similar to the properties passed in a QMF create.....



As I said in my previous reply I'm not suggesting that QMF is in any way perfect, but it certainly has mechanisms for events and query subscriptions (and I like getObjects.....) sure sorting out some of the more untidy request/response semantics and moving away from the amq.default.direct/amq.default.topic to being able to address the Management Node directly all seem reasonable, but I still think that an evolution from that rather than trying a ground up approach would have made things easier - a lot of the conversations around AMQP 1.0 Management have seemed to be around things that already work pretty well in QMF.

Clearly we are where we are and the most important thing now is to make sure that AMQP 1.0 Management evolves, grows and achieves wide adoption and I for one am certainly keen to see that happen and be supportive of it, but that shouldn't stop me voicing the odd bit of frustration or getting on my soap-box every now and again :-D


I completely agree that number of mallocs makes sense for some
implementations... but it certainly doesn't make sense for all.  What I
want to see is that we have something that says "here's how you do common
operations agaisnt any type of object - including some sort of event
stuff", along side: "here are the common attributes, methods defined for
these common entity types... though your vendor will likely have all sort
of other goodies on top".
That all sounds fair enough.

  One thing to remember is that for AMQP 1.0,
we're not only thinking about the sort of role that QMF played for Qpid...
but also the fact that in AMQP 1.0 there is no longer a way of creating
queues programmatically... So the basic case that we wanted to cover
quickly is a way to programmatically dynamically create (non temporary)
queues and such.
So I get that, though FWIW:
1) "in AMQP 1.0 there is no longer a way of creating queues programmatically " does really bug me. I'd love to know the reason for this - is the answer "politics"? Do some vendors not have this ability hence it couldn't be specified or they wouldn't sign up? Being able to create a named node with specified properties seems a pretty reasonable use case so why AMQP 1.0 doesn't allow it is utterly beyond me I'm afraid. 2) I'm not convinced that AMQP 1.0 Management (or QMF) are the most enjoyable way to programmatically do this. It's still quite an annoying faff to do a request/response and populate all the Map body etc. *just to create a queue*. I'd accept that AMQP 1.0 Management makes it a little less of a faff than QMF2, but it's only just a little less of a faff. 3) If I'm honest I think that I prefer Gordon's QueuePolicy/TopicPolicy where you administratively create what amounts to a factory that gets triggered by a link attach (there's clearly nothing to stop you creating queues via AMQP 1.0 Management too but "forcing" people to faff around with request/reponse/Maps is nobody's idea of fun IMHO) qpid-config add TopicPolicy header-exchange-* --argument exchange-type=headers --argument auto-delete=false --argument alternate-exchange=amq.match --argument qpid.ive=1 --argument qpid.msg_sequence=1 ./drain --connection-options {protocol:amqp1.0} -b localhost -f "header-exchange-test"

   The wider management use cases perhaps haven't been as
completely explored yet as they could be... And certainly having those who
can contribute directly, and those who can't be members of OASIS contribute
their thoughts to the Technical Committee through the TC comments mailing
list would be of great value!

I guess that's reasonable, though between the Java Broker UI and the QMF UI we've probably got a good subset of the broker use cases covered. I suspect that the more interesting unexplored use cases are around the ability to use AMQP 1.0 Management more generally to manage other containers (such as clients) - though TBH that's a similar use case that the QMF Agent mechanism addressed.

At the risk of getting dragged into a protocol versus API debate I think that there's some argument for having a management API so that massive amounts of wheel reinvention doesn't end up happening every time someone wants to enable AMQP 1.0 Management capabilities to their container.

The argument for an API probably isn't too strong if it's only about managing the brokers, but it's stronger if we want to make it easy to add useful management to arbitrary containers.


So, my view is that the JMX API will stay as it is (forever more).  For the
REST API I think we would try to migrate people as seamlessly as possible
when attribute names changed or the semantics of operations did so...
however we are very deliberately not at a 1.0 release because I think there
are likely to be breakages in the APIs until we get stuff nailed down as a
community, and hopefully in the wider AMQP world.

Yeah, all that sounds entirely reasonable. It feels quite an exciting time to be part of the Qpid (and AMQP) community. I feel a little happier now that I'm starting to get my head around AMQP 1.0 a bit more, though it'll be nice when the AMQP 1.0 stuff starts to stabilise - in particular it'll be good when the JMS client reaches "mission-critical ready".


One other thing that I keep forgetting to mention; in QMF2 Agents broadcast heartbeat messages periodically to a topic so clients can identify if Agents have gone away. I guess that this is perhaps more useful in QMF2 where Agents aren't *necessarily* co-located with the Broker, but it has got me thinking. In AMQP 1.0 Management I guess that the $management node is likely to be pretty coupled to the Container's lifecycle such that a client could probably infer that the $management node is gone based on interception of a connection failure (e.g. via something like a Connection Exception Listener) but a couple of use cases fall out of that sort of scope: 1) What about Management nodes other than $management? It's possible that the Container and $management might be available, but some other Management node a user is interested in might possibly die asynchronously for whatever reason (a simple use case might be one client DEREGISTERing a Management Node that another client happens to be using). 2) What about Message-oriented (as opposed to Connection-oriented) APIs such as Messenger, with those the fact of Connection closing wouldn't necessarily register until the next time a request was made.

Clearly a Management client could figure this out by some sort of polling - and that might be better than needing a topic to broadcast a heartbeat (though it doesn't scale as well if there are lots of clients) but if polling is the expected way to accomplish this then I'd say that the Management Specification needs to specify a standard Management node operation to achieve this (perhaps STATUS ?). For someone designing a decoupled client (say a WebApp) being able to determine the status of Management nodes and provide feedback to the user is pretty useful.

Cheers,
Frase



Reply via email to