[
https://issues.apache.org/jira/browse/QPIDJMS-220?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15673647#comment-15673647
]
Robbie Gemmell edited comment on QPIDJMS-220 at 1/12/17 2:40 PM:
-----------------------------------------------------------------
The following details an idea around a mechanism to support shared
subscriptions, and how that can be used in the JMS client.
h4. Short Version:
A 'SHARED-SUBS' connection or link capability is used to establish support for
the shared subscriptions mechanism.
A named \[shared\] subscription is identified using the link name.
The subscription identity can be scoped to the AMQP container, i.e. it is
unique within the scope of connections using the same container-id, or it can
be global, in which case the subscription identity is independent of the
container-id and can be used by receivers on any connection with any
container-id. A global subscription identity is indicated by adding the symbol
'global' to the Source capabilities.
A subscription may be shared by more than one consuming link, in which case the
messages for the subscription are distributed between all the consuming links.
To indicate that the link is for a shared subscription the symbol 'shared' is
added to Source capabilities.
AMQP requires that link names are unique in a given direction between two
containers, identified by the container-id specified in the Open frame. In
order to allow multiple links consuming from the same shared subscription on
connection(s) with the same container-id a link naming scheme is proposed such
that only the part of the link name up to (but excluding) a '|' character is
used for establishing the name of the subscription the link refers to. E.g. the
link names "mysub|foo" and "mysub|bar" would both be interpreted as referencing
a subscription named 'mysub' (which could then be durable or non-durable, and
global or container scoped), but as the two names are different they could be
used on the same connection or connections with the same container-id. Clients
would then utilise this where necessary to ensure unique link names are
utilised. The details after the "|" have no semantics associated with them, and
are only used to distinguish one link name from another while referencing the
same subscription name.
==============
h4. Longer version:
h6. Intro/Background:
JMS 1.1 has volatile and durable single-consumer topic subscriptions. Durable
subscriptions have a name, and these names are scoped within a ClientID, with a
single Connection being able to use a given ClientID at a time, and a ClientID
being mandatory to use a durable subscription.
JMS 2.0 added support for shared volatile and durable subscriptions, such that
for a given subscription name multiple consumers can consume from the same
subscription to spread processing load. It also makes ClientID optional for
these shared subscriptions, with different behaviour given depending on whether
a ClientID is set or not. If a ClientID is set, this means that only
subscribers on the same Connection can share the subscription. If a ClientID is
not set then subscribers from any Connection without a ClientID can share the
subscription. Non-shared durable subscriptions require a ClientID as in JMS 1.1
before. Shared durable and non-shared durable subscriptions use a single a name
space when a ClientID is set and can't co-exist.
The above essentially gives 5 separate subscription spaces:
Durable (shared + non-shared) with ClientID
Shared Volatile with ClientID
Shared Durable without ClientID
Shared Volatile without ClientID
Non-shared Volatile (regardless of ClientID status)
h6. Existing non-shared subscriber behaviour (used for JMS 1.1):
For single-consumer durable topic subscriptions, the client attaches a
receiving link, using the subscription name as the link name, and with a Source
having the address of the topic, a terminus durability of 1 or 2, a terminus
expiry of never, and filters to reflect selector/no-local. The connections
container-id contains the ClientID (which is required for non-shared durable
subscriptions) and as links are scoped to container-id this satisfies the
ClientID-scoping required for such subscriptions names. Closing (rather than
just detaching) the link represents end/unsubscribe of the subscription, and
this is utilised by Session#unsubscribe by attaching a receiving link using the
subscription name, with a null Source, requiring the server to perform a lookup
for an existing subscription using this link name. If none is found then the
link is refused and the client throws an exception, otherwise it closes the
opened link to provoke unsubscribe.
Link Name Examples:
{noformat}
With a ClientID: mySubscriptionName
Without ClientID: N/A, must have ClientID to use.
{noformat}
For single-consumer volatile topic subscriptions, the client attaches a
receiving link, using a generated link name, and with a Source having the
address of the topic, a terminus durability of 0, a terminus expiry of
link-detach, and filters to reflect selector/no-local.
Link Name Examples:
{noformat}
With or without a ClientID: <generated>
{noformat}
h6. New shared subscriber behaviour:
We need a mechanism to support the additional shared (and existing non-shared)
subscription behaviours, being able to convey:
\- Whether the mechanism is requested / supported / in-use.
\- A subscription name (accounting for required name spacing).
\- The address of the topic being subscribed to.
\- Whether the subscription is durable (and implicitly also how/when it could
be/is removed)
\- Whether it is shared or not.
\- Any selector or no-local (N/A for shared sub) filters.
\- We need to be able to signal removal of durable subscriptions given only the
subscription name, as that is all Session#unsubscribe gives us.
\- Implicitly or explicitly how to handle change of address/filters for a given
subscription.
h6. Inspecting support for shared subs
Since JMS explicitly offers the shared subscriptions via API, and it is
actually going to be supported via a layered mechanism, we need a mechanism to
detect \[lack of\] support and avoid confusion where specific servers don't
actually support it.
The proposal is to use a "SHARED-SUBS" connection capability or link capability
for this. If a server offers the connection capability, it is indicating that
any topic address can be used for shared subscriptions. A simple broker might
do this for example. On the other hand, a given server might not want/be able
to support this for any address but rather only specific addresses. Imagine
that Qpid Dispatch Router is being used to accept connections and facilitate
link routing to back end brokers, but additionally also facilitate direct
client to client messaging through the router mesh. In this scenario, some
addresses may support this behaviour while others might not, and so the router
offering the connection capability would be inappropriate.
If the connection capability is not offered by a server, the client can instead
use a link capability for detecting support. If the opened link does not offer
support for the capability when requested, the client can interpret this as a
lack of support and throw an exception accordingly.
h6. Shared Volatile Subscription
Starting from the non-shared volatile scenario, we additionally need to convey
that it is a shared sub, give the subscription name, and whether to share the
subscription within a single container or across multiple containers (i.e the
ClientID set vs no ClientID scenario).
We need to indicate that we want to share the subscription between multiple
subscribers by adding a "shared" capability to the Source. Similarly to the old
durable subscription case, we make the link name contain the subscription name.
AMQP requires that link names are unique in a given direction between two named
containers, however we also desire sharing on a single connection (in JMS, this
is actually required to share at all when a ClientID is set). To facilitate
this, we need a scheme by which such links can be disambiguated while still
retaining the ability to identify the same subscription name. To do this, we
propose to consider only the part of the link name up to (but excluding) a '|'
character for establishing the identity of the subscription the link refers to,
with the remainder being used only to disambiguate the different links from
each other. E.g. the link names "mysub|foo" and "mysub|bar" would both be
interpreted as referencing subscription name 'mysub' (which could be durable or
non-durable, and global or container scoped) but but as the two names are
different they could be used on the same connection. The detail after the "|"
has no semantics associated with it, and is only used to distinguish one links
name from another using the same subscription name, for example by using a
counter to index names for a subscription, and qualifiers to aid operators.
For the shared volatile subscription, the link terminus expiry is 'link-detach'
and there is no behavioural difference associated with whether the link is
detached with close=true or false, the subscription is considered ended when
the last subscriber detaches.
Link Name Examples:
{noformat}
With a ClientID: mySubscriptionName|volatile1 (then 2,3,etc)
Without ClientID: mySubscriptionName|global-volatile1 (then 2,3,etc)
{noformat}
h6. Shared Durable Subscription
Starting from the non-shared durable scenario. We additionally need to convey
that it is a shared sub, and whether to share the subscription within a single
container or across multiple containers (i.e the ClientID set vs no ClientID
scenario).
We again use the "shared" and "global" source capabilities as outlined for the
volatile subscription. Since shared and non-shared durable subscriptions can't
coexist with the same name, they use the same initial link name. Subsequent
shared subscribers for a given shared subscription then distinguish their link
names with a suffix using the mechanism described above. When a ClientID is not
set, the link is qualified with a suffix indicating it is a global subscription
link.
For the shared durable subscription, the link terminus expiry is 'never' and
the terminus is durable. Detaching the link leaves the subscription in place.
For the purposes of ending the subscription, closing the link is used to signal
intent to end the subscription (as in the non-shared case). If there are no
other active consumers this succeeds, but if there are other active consumer
links a detach with error is returned to the client.
{noformat}
With a ClientID: mySubscriptionName
With a ClientID: mySubscriptionName|2 (then 3,etc)
Without ClientID: mySubscriptionName|global
Without ClientID: mySubscriptionName|global2 (then 3,etc)
{noformat}
h6. Unsubscribe
Closing (detach with closed=true) a link ends the subscription, except if in
use by other subscribers (see server enforcement details below). For non-JMS
clients this can be any existing link. For JMS clients, a specific new link
must be attached knowing only the name of the subscription, as unsubscribe is
an explicit operation of the session.
During unsubscribe, if a ClientID is set on the connection, a link named with
the subscription name would be used to perform a 'null source lookup' for the
subscription, as it is already for the existing non-shared durable
subscriptions (see earlier for behaviour outline). If a ClientID is not set,
the "|global" suffix will be added as shown previously, e.g:
{noformat}
With a ClientID: mySubscriptionName
Without ClientID: mySubscriptionName|global
{noformat}
Additionally, while using connections that dont have a ClientID set, i.e using
global shared susbcriptions, the link will have "shared" and "global" desired
capabilities added as hints to the server that this is an attempt to attach to
a 'global' shared subscription of the appropriate name derived from the link,
aiding the server should no link with this name be known by it for the
particular client container-id currently in use.
h6. Server handling:
Servers will need to handle/provide the following behaviours:
\- Durable and volatile subscribers are distinct, may use same subscription
names (but not *link* names) concurrently.
\- Container-scoped and 'global' subscribers being distinct, i.e may use same
subscription names (but not *link* names) concurrently.
\- Refusing a shared subscriber link using the same link name as for an
existing non-shared subscription (and vice versa).
\- Refusing a global subscriber link using the same link name as for an
existing non-global subscription (and vice versa).
\- Changing topic/selector and reinitializing an existing sub with no active
subscribers
\- Refusing link trying to change topic/selector for existing sub with active
subscribers
\- Refusing to end an otherwise active subscription (e.g unsubscribe from
another connection while there is no ClientID set)
was (Author: gemmellr):
The following details an idea around a mechanism to support shared
subscriptions, and how that can be used in the JMS client.
h4. Short Version:
A 'SHARED-SUBS' connection or link capability is used to establish support for
the shared subscriptions mechanism.
A named \[shared\] subscription is identified using the link name.
The subscription identity can be scoped to the AMQP container, i.e. it is
unique within the scope of connections using the same container-id, or it can
be global, in which case the subscription identity is independent of the
container-id and can be used by receivers on any connection with any
container-id. A global subscription identity is indicated by adding the symbol
'global' to the Source capabilities.
A subscription may be shared by more than one consuming link, in which case the
messages for the subscription are distributed between all the consuming links.
To indicate that the link is for a shared subscription the symbol 'shared' is
added to Source capabilities.
AMQP requires that link names are unique in a given direction between two
containers, identified by the container-id specified in the Open frame. In
order to allow multiple links consuming from the same shared subscription on
connection(s) with the same container-id a link naming scheme is proposed such
that only the part of the link name up to (but excluding) a '|' character is
used for establishing the name of the subscription the link refers to. E.g. the
link names "mysub|foo" and "mysub|bar" would both be interpreted as referencing
a subscription named 'mysub' (which could then be durable or non-durable, and
global or container scoped), but as the two names are different they could be
used on the same connection or connections with the same container-id. Clients
would then utilise this where necessary to ensure unique link names are
utilised. The details after the "|" have no semantics associated with them, and
are only used to distinguish one link name from another while referencing the
same subscription name.
==============
h4. Longer version:
h6. Intro/Background:
JMS 1.1 has volatile and durable single-consumer topic subscriptions. Durable
subscriptions have a name, and these names are scoped within a ClientID, with a
single Connection being able to use a given ClientID at a time, and a ClientID
being mandatory to use a durable subscription.
JMS 2.0 added support for shared volatile and durable subscriptions, such that
for a given subscription name multiple consumers can consume from the same
subscription to spread processing load. It also makes ClientID optional for
these shared subscriptions, with different behaviour given depending on whether
a ClientID is set or not. If a ClientID is set, this means that only
subscribers on the same Connection can share the subscription. If a ClientID is
not set then subscribers from any Connection without a ClientID can share the
subscription. Non-shared durable subscriptions require a ClientID as in JMS 1.1
before. Shared durable and non-shared durable subscriptions use a single a name
space when a ClientID is set and can't co-exist.
The above essentially gives 5 separate subscription spaces:
Durable (shared + non-shared) with ClientID
Shared Volatile with ClientID
Shared Durable without ClientID
Shared Volatile without ClientID
Non-shared Volatile (regardless of ClientID status)
h6. Existing non-shared subscriber behaviour (used for JMS 1.1):
For single-consumer durable topic subscriptions, the client attaches a
receiving link, using the subscription name as the link name, and with a Source
having the address of the topic, a terminus durability of 1 or 2, a terminus
expiry of never, and filters to reflect selector/no-local. The connections
container-id contains the ClientID (which is required for non-shared durable
subscriptions) and as links are scoped to container-id this satisfies the
ClientID-scoping required for such subscriptions names. Closing (rather than
just detaching) the link represents end/unsubscribe of the subscription, and
this is utilised by Session#unsubscribe by attaching a receiving link using the
subscription name, with a null Source, requiring the server to perform a lookup
for an existing subscription using this link name. If none is found then the
link is refused and the client throws an exception, otherwise it closes the
opened link to provoke unsubscribe.
Link Name Examples:
{noformat}
With a ClientID: mySubscriptionName
Without ClientID: N/A, must have ClientID to use.
{noformat}
For single-consumer volatile topic subscriptions, the client attaches a
receiving link, using a generated link name, and with a Source having the
address of the topic, a terminus durability of 0, a terminus expiry of
link-detach, and filters to reflect selector/no-local.
Link Name Examples:
{noformat}
With or without a ClientID: <generated>
{noformat}
h6. New shared subscriber behaviour:
We need a mechanism to support the additional shared (and existing non-shared)
subscription behaviours, being able to convey:
\- Whether the mechanism is requested / supported / in-use.
\- A subscription name (accounting for required name spacing).
\- The address of the topic being subscribed to.
\- Whether the subscription is durable (and implicitly also how/when it could
be/is removed)
\- Whether it is shared or not.
\- Any selector or no-local (N/A for shared sub) filters.
\- We need to be able to signal removal of durable subscriptions given only the
subscription name, as that is all Session#unsubscribe gives us.
\- Implicitly or explicitly how to handle change of address/filters for a given
subscription.
h6. Inspecting support for shared subs
Since JMS explicitly offers the shared subscriptions via API, and it is
actually going to be supported via a layered mechanism, we need a mechanism to
detect \[lack of\] support and avoid confusion where specific servers don't
actually support it.
The proposal is to use a "SHARED-SUBS" connection capability or link capability
for this. If a server offers the connection capability, it is indicating that
any topic address can be used for shared subscriptions. A simple broker might
do this for example. On the other hand, a given server might not want/be able
to support this for any address but rather only specific addresses. Imagine
that Qpid Dispatch Router is being used to accept connections and facilitate
link routing to back end brokers, but additionally also facilitate direct
client to client messaging through the router mesh. In this scenario, some
addresses may support this behaviour while others might not, and so the router
offering the connection capability would be inappropriate.
If the connection capability is not offered by a server, the client can instead
use a link capability for detecting support. If the opened link does not offer
support for the capability when requested, the client can interpret this as a
lack of support and throw an exception accordingly.
h6. Shared Volatile Subscription
Starting from the non-shared volatile scenario, we additionally need to convey
that it is a shared sub, give the subscription name, and whether to share the
subscription within a single container or across multiple containers (i.e the
ClientID set vs no ClientID scenario).
We need to indicate that we want to share the subscription between multiple
subscribers by adding a "shared" capability to the Source. Similarly to the old
durable subscription case, we make the link name contain the subscription name.
AMQP requires that link names are unique in a given direction between two named
containers, however we also desire sharing on a single connection (in JMS, this
is actually required to share at all when a ClientID is set). To facilitate
this, we need a scheme by which such links can be disambiguated while still
retaining the ability to identify the same subscription name. To do this, we
propose to consider only the part of the link name up to (but excluding) a '|'
character for establishing the identity of the subscription the link refers to,
with the remainder being used only to disambiguate the different links from
each other. E.g. the link names "mysub|foo" and "mysub|bar" would both be
interpreted as referencing subscription name 'mysub' (which could be durable or
non-durable, and global or container scoped) but but as the two names are
different they could be used on the same connection. The detail after the "|"
has no semantics associated with it, and is only used to distinguish one links
name from another using the same subscription name, for example by using a
counter to index names for a subscription, and qualifiers to aid operators.
For the shared volatile subscription, the link terminus expiry is 'link-detach'
and there is no behavioural difference associated with whether the link is
detached with close=true or false, the subscription is considered ended when
the last subscriber detaches.
Link Name Examples:
{noformat}
With a ClientID: mySubscriptionName|volatile1 (then 2,3,etc)
Without ClientID: mySubscriptionName|global-volatile1 (then 2,3,etc)
{noformat}
h6. Shared Durable Subscription
Starting from the non-shared durable scenario. We additionally need to convey
that it is a shared sub, and whether to share the subscription within a single
container or across multiple containers (i.e the ClientID set vs no ClientID
scenario).
We again use the "shared" and "global" source capabilities as outlined for the
volatile subscription. Since shared and non-shared durable subscriptions can't
coexist with the same name, they use the same initial link name. Subsequent
shared subscribers for a given shared subscription then distinguish their link
names with a suffix using the mechanism described above. When a ClientID is not
set, the link is qualified with a suffix indicating it is a global subscription
link.
For the shared durable subscription, the link terminus expiry is 'never' and
the terminus is durable. Detaching the link leaves the subscription in place.
For the purposes of ending the subscription, closing the link is used to signal
intent to end the subscription (as in the non-shared case). If there are no
other active consumers this succeeds, but if there are other active consumer
links a detach with error is returned to the client.
{noformat}
With a ClientID: mySubscriptionName
With a ClientID: mySubscriptionName|2 (then 3,etc)
Without ClientID: mySubscriptionName|global
Without ClientID: mySubscriptionName|global2 (then 3,etc)
{noformat}
h6. Unsubscribe
During unsubscribe, if a ClientID is set, a link named with the subscription
name would be used to perform a 'null source lookup' for the subscription, as
it is already for the existing non-shared durable subscriptions (see earlier
for behaviour outline). If a ClientID is not set, the "|global" suffix will be
added as shown previously, e.g:
{noformat}
With a ClientID: mySubscriptionName
Without ClientID: mySubscriptionName|global
{noformat}
Additionally, while using connections that dont have a ClientID set, i.e using
global shared susbcriptions, the link will have "shared" and "global" desired
capabilities added as hints to the server that this is an attempt to attach to
a 'global' shared subscription of the appropriate name derived from the link,
should no link of this name be known by the server for the particular
connection container-id currently in use.
h6. Server handling:
Servers will need to handle/provide the following behaviours:
\- Durable and volatile subscribers are distinct, may use same subscription
names (but not *link* names) concurrently.
\- Container-scoped and 'global' subscribers being distinct, i.e may use same
subscription names (but not *link* names) concurrently.
\- Refusing a shared subscriber link using the same link name as for an
existing non-shared subscription (and vice versa).
\- Refusing a global subscriber link using the same link name as for an
existing non-global subscription (and vice versa).
\- Changing topic/selector and reinitializing an existing sub with no active
subscribers
\- Refusing link trying to change topic/selector for existing sub with active
subscribers
\- Refusing to end an otherwise active subscription (e.g unsubscribe from
another connection while there is no ClientID set)
> add support for shared topic subscriptions
> ------------------------------------------
>
> Key: QPIDJMS-220
> URL: https://issues.apache.org/jira/browse/QPIDJMS-220
> Project: Qpid JMS
> Issue Type: Sub-task
> Components: qpid-jms-client
> Reporter: Robbie Gemmell
> Assignee: Robbie Gemmell
>
> JMS 2.0 adds support for shared volatile and durable topic subscriptions.
> Whilst at its simplest this logically reduces to consuming messages from a
> shared backing queue representing the subscription, there are however many
> details to consider and a mechanism is needed for conveying the required
> details/behaviours using AMQP 1.0. This JIRA serves to capture information
> regarding this, both as it applies to AMQP clients/servers in general, and
> specifically to the JMS client.
> Sub-task of QPIDJMS-207
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]