New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ARTEMIS-2614 Create queues based on FQQN for AMQP protocol #3124
Conversation
That's not technically true. The broker supports auto-creation of addresses and queues. When auto-creating resources the routing type is based on the following (in descending order of precedence):
|
That's true, but not when you specify address+queue using FQQN. If you do, it will attach to any address+queue combination that matches irrespectively of the defined routing type. If the queue doesn't exist, it won't be auto-created. |
TerminusDurability is not the same thing as queue durability and so shouldn't be used for indicating such. |
But currently seems to be used that way, isn't it? |
Of course, but that wasn't my point. My point was simply that the resources didn't have to pre-exist in the first place (i.e. without FQQN) as you seemed to assert. |
@jbertram Yes, but why should we consider not FQQN based scenarios? |
No. It is only used in one place, appropriately, to indicate the subscription to a topic node is durable or not. That is, the link/terminus is durable or not. Not the queue the broker happens to create (which is an implementation detail, there need not be any queue). |
@gemmellr I am not sure I follow. Isn't this just JMS limitation? What I'm aiming for here is to support programmatically what is already supported via broker configuration and via GUI. |
@Havret, I suppose I misunderstood what you were asserting in your original comment when you were talking about how "the implementation assumed pre-existence of the queue." |
By "programmatically" you mean specifically from an AMQP client, right? You can already create the resources any client would need programmatically through the management API. |
@jbertram No worries. I suppose I could've been more specific. :)
Yep, exactly that's my goal. |
@Havret No its not related to JMS. TerminusDurability is simply not equal to queue durability. For example, were you to conflate terminus and queue config like that, I'd note that the terminus expiry policy would then dictate the broker should be deleting your queues when you go away in almost all situations. Which is typically not going to be preferred behaviour for most folks, and fortunately isnt the case since terminus != queue. The core AMQP spec doesn't deal with creation of nodes (queues/topics/others), which again reinforces terminus durability isnt queue durability. Its expected other mechanisms are used for fine grained creation of nodes (queues/topics/others) such as layered management like Artemis own existing management abilities Justin notes, which can be used using AMQP messages also, or alternatively the AMQP Management layered [draft] spec. |
@gemmellr
In Artemis Docs it is stated.
The whole effort I am making here is just a result of a discussion on the mailing list where Martyn Taylor said:
Regarding the part:
This sounds really promising! It is almost like it is done in RabbitMQ. Could you please point me where I can find more regarding this API? |
The management API generally and management messages in particular are both discussed in the documentation. The documentation discusses this mainly in terms of core and JMS. The broker ships the management example where you can see management messages in action. You can also see an example of an AMQP client using management messages in the test-suite. |
This isnt the same. The client is creating a subscription to a 'topic' node's address, it says nothing about queues or their durability. It asks for the link terminus to be retained or not. For the durable-subscription case it specifically sets a terminus expiration of never, that is the terminus (/subscription) should be retained when it goes away. In the 'shared' cases there is a further layered mechanism (which has been negotiated as supported) further governing the behaviour of 'shared', 'global', link names etc. In no case does the client ask for a specific queue to be made, durable or otherwise, its simply a broker implementation detail that the broker chooses to model its 'topic' subscriptions as a queue encoding details such as a particular name. If nothing else you will break things for most existing usage if you were to now conflate terminus and queue durability at this point when they never have been before. Similarly if you conflate Terminus config with queue config, youd really also need to conflate terminus expiry with the queue lifecycle. As earlier, in most cases (i.e mostly everything except 'never', as above) thats going to result in a queue being deleted when you dont want. The core spec does not deal with regular queue creation, so it also doesnt cater to their durability, terminus durability isnt queue durability.
Its not something I have used, but Justin looks to have already linked to the details I was aware of in his last post above. One place I know it is actually used as part of doing Artemis management using AMQP messages is: |
@gemmellr I believe that your opinion is a little bit biased, as you're looking at AMQP as the implementation detail for JMS. I don't believe this is the case. Artemis as it is doesn't care about |
I'm really not looking at it that way at all. I'd say I more typically advocate for not catering to JMS specifically, since AMQP is entirely separate from JMS, regardless whether a certain JMS client I work on uses it. That I can recall, JMS hasn't really even entered my replies here except largely dismissing it as a factor when you keep bringing it up (one last time though: those bits you refer to are not only for JMS clients, other AMQP clients can and do use them). This discussion has zero dependence on JMS in my mind. I'm looking at this in terms of the AMQP spec itself, and having discussed this area previously with folks who actually wrote it. Terminus durability isnt queue durability. Again, the core spec does not cover queues or creating them, it simply attaches to nodes [configured out of band] with a given address. You would similarly break behaviour for any AMQP client out there using FQQNs already by all of a sudden considering terminus durability to be queue durability. |
@gemmellr I'm bringing up JMS because JMS-AMQP mapping was the first thing you referred me to. Speaking in terms of AMQP spec, words like
And I see this being used to implement JMS features I interpret it this way. Shared Durable Subscription that you're recalling as the only feasible case to use TerminusDurability is not an AMQP feature. It's a way that JMS based clients can attach to multicast queues where topic maps to address and subscription name maps to durable queue name. The fact that the durable queue is created there, is not an implementation detail from my perspective. When I configure broker I'm not configuring it in terms of topics and subscriptions. When I use FQQN I don't even need to know that such things exist. I have a broker with configured addresses and queues and I want to attach to them. In the ideal world, it would be great if it was possible to do it without the need to pre-configure (for instance to make development easier). |
I didn't refer you to it. Someone else may have briefly linked to it.
Topic and subscriptions aren't AMQP specific terms (or JMS specific), though are generally understood messaging concepts, but since the spec doesn't deal specifically with queues or topics, merely nodes, plus links, terminus etc, their lack of use isnt surprising to me. You are correct that the 'shared' and 'global' terms arent in the draft JMS mapping document either, because I have yet to publish the update with them in it. I did only mention those terms after you brought up shared durable subscriptions however, and again I didn't actually direct you to that document. JMS has no special bearing in this discussion from my view, its purely AMQP from my perspective.
Thats fair enough. You could possibly include in that resource list, discussion from those who people might say are quite familiar with the area, and are indicating having discussed this very specific item with authors on more than one occasion (including yesterday).
Specifically the doc section it appears you may be quoting from is "AMQP and Multicast Addresses (Topics)", i.e its about topics rather than queues, aligning with what I have said. The broker models its 'topic' subscriptions (i.e consumer link attaching using address of, err, an address ) using a queue that it happens to expose. There is no need for an actual exposed queue here at all, its a topic subscription, the queue is essentially a synthetic creation. It is the link terminus attaching to the topic-like node (so, address), i.e effectively the subscription representation, that is being indicated as durable (and separately marked as never expiring, to ensure its contuing existance) in this case to retain it. This is quite a different situation than if the link terminus were intended for attaching directly to an actual queue.
I am not saying (and dont recall ever having done so here) that Shared Durable Subscriptions are the only feasible case for TerminusDurability. I have said topic-like subscriptions of any kind are the main use case for it (along with expiry in some cases). I have said that TerminusDurability isnt the same direct thing as queue durability. The spec doesnt deal with creating them and so doesn't deal with their durability. Separately though, they are however an AMQP feature - a layered extension feature yes, but a fully negotiated one that any AMQP client or server can use doing regular AMQP interactions, and again already do. Not really important, but for historic clarity, as it happens shared AMQP subscriptions existed in actual use in non-JMS client and servers long before any work was done in that area for a JMS 2 mapping for use in AMQP JMS clients. That existing behaviour was used as a starting point of reference (and one of many many approaches looked at) and expanded slightly to cover other requirements.
All AMQP clients or servers attach to 'topic-like' nodes (in this case, the brokers 'addresses') in the same way, not just JMS ones. Again, the queue existing in this scenario is completely a broker implementation detail (an approach that others also choose, admittedly), and it is entirely possible to model that topic subscription without any exposed queue.
I understand that it might be a nice side effect that you desire in certain cases, but that doesnt mean it isnt an impl detail, or that terminus durability is queue durability. |
The way I know some other servers have facilitated things in this space is to enable pre-defining configuration that will apply to a queue/topic/other when things are being auto created, e.g allowing you to pattern match what configuration that applies when a link attaches to a given address. Possibly much like the the existing address config stuff can pre-configure address behaviour without actual addresses. |
9f61beb
to
51210d3
Compare
So after all it wasn't too productive discussion. I debugged the code, and apparently methods However, there are still some things that need to be cleared up regarding my first question.
STOMP implementation that @jbertram recently added #3018 seems to silently ignore passed routing type when the mismatch occurs. Should I do the same here? It would be the safest way I guess, but what do you guys think? |
First off you shouldn't affect the existing logic, e.g. the original use case which was to allow a fqqn to bind to a queue matching the name ignoring the routing type. E.g. if a fqqn matches an existing queue it should bind to it regardless routingtype. For stomp how its done is" A RoutingType is passed to the autoCreateDestinationIfPossible method which is based on the frame's header or destination prefix. If that is null then it uses the default value specified in the address-settings. |
If you look in ProtonServerSenderContext, there already is a field derived and caclulated "routingTypeToUse" Also i would use the same logic already in there thats working out if its a durable or non-durable queue (aka if its volatile) |
So the routing type is calculated there multiple times, using slightly different variations of the same logic. It's pretty messy tbh, maybe it would be a good idea to unify this, and extract one method to determine routing type. The same story with fields |
To be honest i would expect for FQQN it to apply all the exact logic thats in there, except the where we call createQueueName you use queueNameToUse if it present instead, that was possibly extracted earlier in the composite address extraction e.g. line 413
to
And like wise line 438 extactly the same I wouldnt expect changes anywhere else to achieve what you wanted, e.g. no change to any other class or area of the code base, a very small extra if then else around the queue name used |
I wish it was that simple. Unfortunately for anycast routing type we don't even get to this line. For multicast on the other hand,
in the original line 414 will throw an exception as the queue doesn't exist. There is quite a lot of code here, and a lot of non-obvious stuff is going on, that's why I wanted to break the flow and handle FQQN in separation to the old bits. |
For anycast i wouldnt even bother, the anycast queue is expected to have been created when the queue address is, for JMS semantics anyhow. (E.g. the original remit of FQQN was allowing a JMS queue consumer bind to a mutlicat queue, to get around issues where a JMS client was still at 1.1 spec without shared sub support ) re Topic (aka multicast) Thats just original logic added for FQQN, getMatchingQueue, so just change line 515 e.g. this
to return null, instead of throw exception (as like for non fqqn) do keep the rest of it. |
So if I make these changes, it will work partially for multicast routing type (but all queues will be created using Any suggestions?
But we would end up with the implementation that's not in sync with what's available for instance for STOMP. The whole point of this PR was to make it right, and easier to utilize for non-JMS AMQP based clients. |
51210d3
to
997e77b
Compare
For AMQP clients they should really be using correct structures of AMQP not coding to FQQN. Its intent was solely for JMS legacy workaround where client has not yet upgraded to JMS 2 which supports shared subs etc. And in JMS 2.0 Amqp client like qpid they correctly set the amqp structures. This was focussed on jms 1.1 legacy usecases as a bridging mechanism where client upgrade to 2.0 wasnt yet feasible. For non jms usecase in amqp, then should advocating using the correct amqp structures. E.g. in your case such where NMS doesnt yet support 2.0 (wip) then youre restricted to fqqn for shared subs. Obviously the whole issue is removed when we get NMS 2.0 upto 2.0 spec. As such i would just assume in code that if fqqn and queue not found it is a multicast you want to create on |
1a0ef58
to
603a0d0
Compare
603a0d0
to
bfcb3cf
Compare
Just to note and for the record, i am cautious of this change, as the FQQN was added for legacy stuff, making this change could be impacting to those expected behaviours. And building on it further encourages its use to proliferate. Unlike stomp, which you bring up, AMQP has a very rich messaging structure that supports this, as such its not like comparing stomp or openwire which are limited, in this area. Personally i think for any higher level AMQP clients (e.g JMS/NMS) they would be better to expend time into adding support for the equivalent of jms shared sub in their abstractions, , so in case of NMS that would be to get that updated to similar spec level with JMS 2.0 I guess mapping would be for JMS 1.1 for fqqn genreated depending on the consumer the client made in jms api. JmsQueueConsumer (createConsumer(Queue)-> shared durable For nonshared, non durable a user would just not use FQQN. Def need tests for the above., and all the combinations. You could look to make use of ParameterisedAddress (re use, like CompositeAddress is) like in Core to get extra queue config for a queue off the name, to allow for more configuration to be able to be present in the fqqn address. |
So the behavior shouldn't change unless somebody relies on the fact, that the broker returns an error if one tries to attach to the queue that doesn't exist, instead of simply creating it.
I think this is the current behavior as the only difference between |
I was editing my comment, as hadn;'t fully finished. Mappings i would expect from a black box testing: JmsQueueConsumer (createConsumer(Queue)-> shared durable (aka max consumer = -1, durable=true) For nonshared, non durable a user would just not use FQQN. |
re:
They do, if security settings etc, youll need tests on this. |
I'm not sure if mixing JMS concepts into this is the best idea. Determining whether a queue is durable/non-durable or shared/non-shared based on routing type seems to me pretty non-intuitive. Moreover, the way that JMS differentiate In the ideal world, I would just use
If we create a queue based on FQQN, only if the queue doesn't exist, we wouldn't break any existing users, as they are using FQQN to attach to pre-configured queues anyway. |
Why should it not be the whole feature was to sort a jms issue in 1.1, eradicated the need in a jms 2.0 implementation. E.g. it was a solution to virtual topics (pre jms 2.0 solution for shared subs) for those migrating from amq 5 where the client is jms 1.1 and supported as well for a few other uses where jms 1.1 client maybe used such as earlier qpid jms 1.1 clients predating the jms 2.0 version. As i said as a non jms amqp user using lower level APIs, simply shouldnt be looking to use fqqn, but full amqp native and correct states. I would be certainly -1 this if the idea is to use it outside jms/nms scope for other uses. Fqqn is not transferable and goes against some of AMQP ideals that its broker/client agnostic. E.g. in jms 2.0 it maps correctly to amqp states and is interchange-able any complaint broker, qpid, solace, ibm, etc E.g. the need for fqqn is removed. It certainly shouldnt be encouraged for amqp outside jms 1.1 and even in a jms api should be encouraged to move/upgrade to jms 2.0 so their code will be transferable between compliant brokers. |
Like wise to note as using fqqn with jms, i would expect the broker to behave the same for a jms user if openwire, amqp or core. So anything done here i would expect alignment in core and openwire with agnostic jms test validating this (just switching the jms provider) we do this for many of the cross protocol jms tests. |
If you look at FQQNOpenWireTest youll notice some existing cross protocol (openwire and core aka artemis) tests for JMS, you will want to add AMQP to that, and enhance for any extra cases you want to add, to ensure behaviour across JMS is aligned. |
I would like to -1000 on this. it's already complicated having auto-creating and routing messages. Doing this kind of thing would require doing a lot of computation on queue adding. I don't really think we should use FQQN on auto-create. quite the opposite you should not be using auto-creatin at all on a production system IMHO. If you do, use it for simple cases.. this is definitely not a simple case and it would induce a lot of calculations during simple message routes on regular cases. |
Yes, I totally agree (maybe besides the impact of auto-creation of queues to routing). I followed @jbertram advice and implemented topology management system similar to what is available for RabbitMQ. It is more robust and powerful solution. Sorry for the hassle. I will close this PR by tomorrow. |
@Havret thanks for contributing.. I have seen other nice contributions from you... it's just that I hit another recent issue around mirroring and broker connection that I was working on, and I have seen another issue around this.. when I saw this I came with the -1... that's why I didn't bring this up before. |
I will close it based on the discussion! |
This is my attempt to address the problem of the auto-creation of queues based on FQQN. The simple scenario seems to work, but some decisions need to be made before I can move forward with this.
RoutingType
mismatch. Previously it didn't matter whatRoutingType
receiver tries to attach to, as the implementation assumed pre-existence of the queue. Now the routing type matters, as we need to create a properly configured queue if it doesn't exist. That's whytestQueueConsumerReceiveTopicUsingFQQN
test fails currently. To make it pass I would need to subscribe to a topic instead of a queue. I'm not sure but is this a breaking change or not?testAttachToPreConfiguredNonDurableQueueUsingDurableFQQN
. Should we reject the attempt to attach when the pre-configured queue is non-durable and attach request has the source withTerminusDurability
ofUNSETTLED_STATE
orCONFIGURATION
? And what about the opposite, pre-configured queue is durable and we received source withNONE
value forTerminusDurability
?I would greatly appreciate your help. :)