So I've been doing this FQQN support (ARTEMIS-1093) and I'd like to share my thoughts and current implementations of key functionalities, as well as some concerns. I'd appreciate any comments and adivces to make it better.
More details about FQQN concepts please see official doc: https://github.com/apache/activemq-artemis/blob/master/docs/user-manual/en/address-model.md#fully-qualified-queue-names Simply put, a FQQN takes form of <address>::<queue name>. It uniquely and explicitly identifies a 'queue' entity within a broker. With FQQN any clients can have access to any 'core' queues, so long as the addresses and queue names are known to them. For example, if a core queue "q1" is deployed on address "address1", its FQQN would be "address1::q1". A JMS consumer can receive messages that routed to "q1" by referencing the queue directly using its FQQN, as illustrated in the following code snippet: ... Queue q1 = session.createQueue("address1::q1"); MessageConsumer consumer1 = session.createConsumer(q1); Message m = consumer1.receive(2000); ... Before FQQN, clients using any protocols only can access a queue by its name, which must be unique across all addresses within a broker. If we implement FQQN based on this uniqueness restriction, we don't need change any internal bindings management code. Simply removing the address prefix (like "address1::" in FQQN "address1::q1") from client requests and every thing would work just fine. However, with FQQN in place it is possible that queues of same names can be created on different addresses while still won't lose their uniqueness. For example, "address1::q1" and "address2::q1" are two distinct queues and can perfectly live within a broker together. In this case, a client trying to access one of the queues can't just simply specify the queue name "q1". Because the broker wouldn't know which queue it refers to (ambiguity). To solve this issue, I need to add some 'extra' logic to the existing binding management. Here is what I do: (PR: https://github.com/apache/activemq-artemis/pull/1172 ) 1. Inside broker it used a map (SimpleAddressManager.nameMap) to store bindings (queues) and the keys are queue names. As queue names will no longer be guaranteed to be unique with FQQN, a composite key (BindingKey) is introduced so that the address part of the queues will paticipate in key 'hash' and 'equals' calculation. 2. In order to detect 'ambiguous' binding queries, a new map called uniqueNameMap is added to SimpleAddressManager to keep the number of addresses a binding is bound to. For example if a queue "q1" is bound to both addresses "address1" and "address2", the number stored in this map for "q1" is 2 ("q1"->2). When a binding is added these two maps gets updated. To understand how it works consider the following scenarios: In all of the scenarios below suppose the broker have 3 queues "address1::q1", "address1::q2", "address2::q1" [Scenario 1] A client comes in requesting access to a queue by its name "q2". Broker first checks the uniqueNameMap and finds that there is only one binding for this queue name, no ambiguity, and it goes ahead to get the binding from nameMap and returns it. [Scenario 2] A client comes in requesting access to a queue by its FQQN "address2::q1". Because FQQN is used we don't need to check ambiguity this time. it therefore goes directly to find the binding in nameMap and returns it. [Scenario 3] A client comes in requesting access to a queue by its name "q1". Because there are two bindings (queues) bound to different addresses and client doesn't use FQQN, broker checks the uniqueNameMap and finds that there are more than one (two in this case) bindings exists by the same queue name, in which case it can't determine which one is the one needed. So it gives a warning message and returns null result. Some concerns with my implementation: 1) Although the logic seems straightforward, but the actual code looks like a bit too complex, as some folks pointed out. I'm currently seeking a way to make it simple. Probably separating it into smaller tasks? 2) String manipulations (like concat() and String/SimpleString conversions) added performance cost. Need a way to minimize the impact. Again any comments are welcomed. Thanks, Howard
