-
Type: New Feature
-
Status: Closed
-
Priority: Critical
-
Resolution: Fixed
-
Affects Version/s: 5
-
Fix Version/s: wd07
-
Component/s: core
-
Labels:None
-
Proposal:Hide
A. Add a new definition to 1.2 Terminology
Shared Subscription
A Shared Subscription comprises a Topic Filter and a maximum QoS. Unlike a regular Subscription, a Shared Subscription can be associated with more than one Session and an Application Message that matches a Shared Subscription is only sent to one of these Sessions' clients. A Session can subscribe to more than one Shared Subscription and can contain Shared Subscriptions alongside regular Shared Subscriptions.
B. Update the descriptions of RETAIN in 3.3.1.3 to say that it applies only to non-shared subscriptions
"When a new non-shared subscription is established, the last retained message, if any, on each matching topic name MUST be sent to the subscriber [MQTT-3.3.1-6]. "
...
"When sending a PUBLISH Packet to a Client the Server MUST set the RETAIN flag to 1 if a message is sent as a result of a new non-shared subscription being made by a Client [MQTT-3.3.1-8]."
....
"Retained messages are useful where publishers send state messages on an irregular basis. A new non-shared subscriber will receive the most recent state."C. Change the first paragraph of 3.8.3 (Payload for SUBSCRIBE)
Existing text:
"The payload of a SUBSCRIBE Packet contains a list of Topic Filters indicating the Topics to which the Client wants to subscribe. The Topic Filters in a SUBSCRIBE packet payload MUST be UTF-8 encoded strings as defined in Section 1.5.3 [MQTT-3.8.3-1]. A Server SHOULD support Topic filters that contain the wildcard characters defined in Section 4.7.1. If it chooses not to support topic filters that contain wildcard characters it MUST reject any Subscription request whose filter contains them [MQTT-3.8.3-2]. Each filter is followed by a byte called the Requested QoS. This gives the maximum QoS level at which the Server can send Application Messages to the Client. "Replacement text:
"The payload of a SUBSCRIBE Packet contains a list of Topic Filters indicating the Topics to which the Client wants to subscribe. The Topic Filters in a SUBSCRIBE packet payload MUST be UTF-8 encoded strings as defined in Section 1.5.3 [MQTT-3.8.3-1]. A Server SHOULD support Topic filters that contain the wildcard characters defined in Section 4.7.1. It MAY support Shared Subscription Topic Filters defined in Section 4.9. If it chooses not to support Shared Subscription Topic Filters or Topic Filters that contain wildcard characters it MUST return the appropriate return code in the corresponding SUBACK response [MQTT-3.8.3-2]. Each Topic Filter is followed by a byte called the Requested QoS. This gives the maximum QoS level at which the Server can send Application Messages to the Client. "D. Change the behaviour described in 3.8.4 (SUBSCRIBE response) :
Existing text:
"If a Server receives a SUBSCRIBE Packet containing a Topic Filter that is identical to an existing Subscription’s Topic Filter then it MUST completely replace that existing Subscription with a new Subscription. The Topic Filter in the new Subscription will be identical to that in the previous Subscription, although its maximum QoS value could be different. Any existing retained messages matching the Topic Filter MUST be re-sent, but the flow of publications MUST NOT be interrupted [MQTT-3.8.4-3].If a Topic Filter is not identical to any existing Subscription’s filter, a new Subscription is created and all matching retained messages are sent."
Replacement text:
"If a Server receives a SUBSCRIBE Packet containing a Topic Filter that is identical to a Non-shared Subscription’s Topic Filter for the current Session then it MUST completely replace that existing Subscription with a new Subscription. The Topic Filter in the new Subscription will be identical to that in the previous Subscription, although its maximum QoS value could be different. Any existing retained messages matching the Topic Filter MUST be re-sent, but the flow of publications MUST NOT be interrupted [MQTT-3.8.4-3].
If a Server receives a Non-Shared Topic Filter that is not identical to any Topic Filter for the current Session, a new Non-Shared Subscription is created and all matching retained messages are sent to the client.
If a Server receives a Topic Filter that is identical to the Topic Filter for a Shared Subscription that already exists on the Server, the Session is added as a subscriber to that Shared Subscription. No retained messages are sent.
If a Server receives a Shared Subscription Topic Filter that is not identical to any existing Shared Subscription’s Topic Filter, a new Shared Subscription is created. The Session is added as a subscriber to that Shared Subscription. No retained messages are sent.
See section 4.9 for more details on Shared Subscriptions. "
E. Add new section 4.9 called Subscriptions
MQTT provides two kinds of Subscription, Shared and Non-Shared.
4.9.1 Non-Shared Subscriptions
A Non-Shared MQTT subscription is associated only with the MQTT Session that created it. Each Subscription includes a Topic Filter, indicating the topic(s) for which messages are to be delivered on that Session, and a maximum QoS level. The Server is responsible for collecting messages that match the filter and transmitting them on the Session's MQTT connection if and when that connection is active.
A Session cannot have more than one Non-Shared Subscription with the same Topic Filter, so the Topic Filter can be used as a key to identify the subscription within that Session.
If there are multiple clients, each with its own Non-Shared Subscription to the same Topic, each client gets its own copy of the Application Messages that are published on that Topic. This means that Non-Shared Subscriptions cannot be used to load-balance Application Messages across multiple consuming clients as in such cases you would want each message to be delivered to exactly one client.
4.9.2 Shared Subscriptions
A Shared Subscription can be associated with multiple subscribing MQTT Sessions. Like a Non-Shared Subscription it has a Topic Filter and a maximum QoS, however a publication that matches its Topic Filter is only sent to one of its subscribing Sessions. This makes it suitable for the load-balancing case.
A Shared Subscription is identified using a special style of Topic Filter. The format of this filter is:
$share/
{ShareName}/{filter}
- $share is a literal string that marks the Topic Filter as being a Shared Subscription Topic Filter.
- {ShareName}is a character string that does not include "/", "+" or "#"
- {filter} The remainder of the string has the same syntax and semantics as a Topic Filter in a non-shared subscription - see section 4.7
A Shared Subscription's Topic Filter MUST start with $share/ and MUST contain a ShareName that is at least one character long. The ShareName MUST NOT contain the characters "/", "+" or "#", but MUST be followed by a "/" character. This "/" character MUST be followed by a Topic Filter as described in section 4.7.
Non-normative comment
Shared Subscriptions are defined at the level of the MQTT server, rather than at the level of an individual Session. A ShareName is included in the Shared Subscription's Topic Filter so that there can be more than one Shared Subscription on a server that has the same {filter}component. An application could choose to use the ShareName to represent the group of subscribing Sessions that are sharing the subscription, but it is not obliged to do this.
Examples:
1. Shared subscriptions "$share/consumer1/sport/tennis/" and "$share/consumer2/sport/tennis/" are distinct shared subscriptions and so can be associated with different groups of Sessions. Both of them match the same topics as a non-shared subscription to sport/tennis/+ .
If a message were to be published that matches sport/tennis/+ then a copy would be sent to exactly one of the Sessions subscribed to $share/consumer1/sport/tennis/+ , a separate copy of the message would be sent to exactly one of the Sessions subscribed to $share/consumer2/sport/tennis/+ and further copies would be sent to any clients with non-shared subscriptions to sport/tennis/+2. Shared subscription "$share/consumer1//finance" matches the same topics as a non-shared subscription to /finance.
Note that "$share/consumer1//finance" and "$share/consumer1/sport/tennis/+" are distinct shared subscriptions, even though they have the same ShareName. While they might be related in some way, no specific relationship between them is implied them having the same ShareName.
A Shared Subscription is created by using a Shared Subscription Topic Filter in a SUBSCRIBE request. So long as only one Session subscribes to a particular Shared Subscription, the shared subscription behaves like a non-shared subscription, except that
i) The $share and
{ShareName}portions of the Topic Filter are not taken into account when matching against publications.
ii) No Retained Messages are sent to the Session when it first subscribes. It will be sent other matching messages as they are published.Once a Shared Subscription is in existence it is possible for further Sessions to submit a SUBSCRIBE request with the same Shared Subscription Topic Filter. These additional Sessions could either come from different clients or from different connections from the same client. If the server authorizes an additional SUBSCRIBE request, the new Session gets associated with the Shared Subscription as an additional subscriber. Retained messages are not sent to this new subscriber. Each subsequent Application Message that matches the Shared Subscription is now sent to one and only one of the Sessions that are subscribed to the Shared Subscription.
A Session can explicitly detach itself from a Shared Subscription by sending an UNSUBSCRIBE packet that contains the full Shared Subscription Topic Filter. Sessions also get detached from their Shared Subscriptions when they terminate.
A Shared Subscription lasts for as long as it is associated with at least one Session (i.e. a Session that has issued a successful SUBSCRIBE request to its Topic Filter and that has not completed a corresponding UNSUBSCRIBE). A Shared Subscription survives when the Session that originally created it unsubscribes, unless there are no other Sessions left when this happens. A Shared Subscription ends, and any undelivered messages associated with it are deleted, when there are no longer any Sessions subscribed to it.
Further notes on Shared Subscriptions
1. If there's more than one Session subscribed to the Shared Subscription, the server implementation is free to choose, on a message by message basis, which Session to use and what criteria it uses to make this selection.
2. Different subscribing clients are permitted to ask for different Requested QoS levels in their SUBSCRIBE request packets. The server decides which Maximum QoS to grant to each client, and it is permitted to grant different Maximum QoS levels to different subscribers. When sending an Application Message to a client, the server MUST respect the granted QoS for the client's subscription, in the same that it does when sending a message to a Non-Shared Subscriber.
3. If the server is in the process of sending a QoS 2 message to its chosen subscribing client and the connection to that client breaks before delivery is complete the Server MUST complete the delivery of the message to that client when it reconnects as described in section 4.3.3. If the client's Session terminates before the client reconnects, the Server MUST NOT send the Application Message to any other subscribed client.
4. If the Server is in the process of sending a QoS 1 message to its chosen subscribing client and the connection to that client breaks before the Server has received an acknowledgement from the client, the Server MAY wait for the client to reconnect and retransmit the message to that client when that happens. If the client's Session terminates before the client reconnects, the Server SHOULD send the Application Message to another client that is subscribed to the same Shared Subscription. It MAY attempt to send the message to another client as soon as it loses its connection to the first client.
5. If a client responds with a negative acknowledgement to a PUBLISH packet from the Server, the Server MUST discard the Application Message and not attempt to send it to any other Subscriber.
6. A client is permitted to submit a second SUBSCRIBE request to a Shared Subscription on a Session that's already subscribed to that Shared Subscription - it might for example do this in order to change the Requested QoS for its subscription. This does not increase the number of times that that Session is associated with the Shared Subscription, so the Session will leave the Shared Subscription on its first UNSUBSCRIBE.
7. Each Shared Subscription is independent from any other. It is possible to have two Shared Subscriptions with overlapping filters. In such cases a message that matches both Shared Subscriptions will be processed separately by both of them. If a client has a Shared Subscription and a Non-Shared subscription and a message matches both of them, the client will receive a copy of the message by virtue of it having the Non-Shared Subscription. A second copy of the message will be delivered to one of the subscribers to the Shared Subscription, and this could result in a second copy being sent to this client.
F. Add new sentence to 5.4.2 Authorization of Clients by the Server
An implementation should provide access controls that take place after CONNECT to restrict the client's ability to subscribe to a Shared Subscription.ShowA. Add a new definition to 1.2 Terminology Shared Subscription A Shared Subscription comprises a Topic Filter and a maximum QoS. Unlike a regular Subscription, a Shared Subscription can be associated with more than one Session and an Application Message that matches a Shared Subscription is only sent to one of these Sessions' clients. A Session can subscribe to more than one Shared Subscription and can contain Shared Subscriptions alongside regular Shared Subscriptions. B. Update the descriptions of RETAIN in 3.3.1.3 to say that it applies only to non-shared subscriptions "When a new non-shared subscription is established, the last retained message, if any, on each matching topic name MUST be sent to the subscriber [MQTT-3.3.1-6] . " ... "When sending a PUBLISH Packet to a Client the Server MUST set the RETAIN flag to 1 if a message is sent as a result of a new non-shared subscription being made by a Client [MQTT-3.3.1-8] ." .... "Retained messages are useful where publishers send state messages on an irregular basis. A new non-shared subscriber will receive the most recent state." C. Change the first paragraph of 3.8.3 (Payload for SUBSCRIBE) Existing text: "The payload of a SUBSCRIBE Packet contains a list of Topic Filters indicating the Topics to which the Client wants to subscribe. The Topic Filters in a SUBSCRIBE packet payload MUST be UTF-8 encoded strings as defined in Section 1.5.3 [MQTT-3.8.3-1] . A Server SHOULD support Topic filters that contain the wildcard characters defined in Section 4.7.1. If it chooses not to support topic filters that contain wildcard characters it MUST reject any Subscription request whose filter contains them [MQTT-3.8.3-2] . Each filter is followed by a byte called the Requested QoS. This gives the maximum QoS level at which the Server can send Application Messages to the Client. " Replacement text: "The payload of a SUBSCRIBE Packet contains a list of Topic Filters indicating the Topics to which the Client wants to subscribe. The Topic Filters in a SUBSCRIBE packet payload MUST be UTF-8 encoded strings as defined in Section 1.5.3 [MQTT-3.8.3-1] . A Server SHOULD support Topic filters that contain the wildcard characters defined in Section 4.7.1. It MAY support Shared Subscription Topic Filters defined in Section 4.9. If it chooses not to support Shared Subscription Topic Filters or Topic Filters that contain wildcard characters it MUST return the appropriate return code in the corresponding SUBACK response [MQTT-3.8.3-2] . Each Topic Filter is followed by a byte called the Requested QoS. This gives the maximum QoS level at which the Server can send Application Messages to the Client. " D. Change the behaviour described in 3.8.4 (SUBSCRIBE response) : Existing text: "If a Server receives a SUBSCRIBE Packet containing a Topic Filter that is identical to an existing Subscription’s Topic Filter then it MUST completely replace that existing Subscription with a new Subscription. The Topic Filter in the new Subscription will be identical to that in the previous Subscription, although its maximum QoS value could be different. Any existing retained messages matching the Topic Filter MUST be re-sent, but the flow of publications MUST NOT be interrupted [MQTT-3.8.4-3] . If a Topic Filter is not identical to any existing Subscription’s filter, a new Subscription is created and all matching retained messages are sent." Replacement text: "If a Server receives a SUBSCRIBE Packet containing a Topic Filter that is identical to a Non-shared Subscription’s Topic Filter for the current Session then it MUST completely replace that existing Subscription with a new Subscription. The Topic Filter in the new Subscription will be identical to that in the previous Subscription, although its maximum QoS value could be different. Any existing retained messages matching the Topic Filter MUST be re-sent, but the flow of publications MUST NOT be interrupted [MQTT-3.8.4-3] . If a Server receives a Non-Shared Topic Filter that is not identical to any Topic Filter for the current Session, a new Non-Shared Subscription is created and all matching retained messages are sent to the client. If a Server receives a Topic Filter that is identical to the Topic Filter for a Shared Subscription that already exists on the Server, the Session is added as a subscriber to that Shared Subscription. No retained messages are sent. If a Server receives a Shared Subscription Topic Filter that is not identical to any existing Shared Subscription’s Topic Filter, a new Shared Subscription is created. The Session is added as a subscriber to that Shared Subscription. No retained messages are sent. See section 4.9 for more details on Shared Subscriptions. " E. Add new section 4.9 called Subscriptions MQTT provides two kinds of Subscription, Shared and Non-Shared. 4.9.1 Non-Shared Subscriptions A Non-Shared MQTT subscription is associated only with the MQTT Session that created it. Each Subscription includes a Topic Filter, indicating the topic(s) for which messages are to be delivered on that Session, and a maximum QoS level. The Server is responsible for collecting messages that match the filter and transmitting them on the Session's MQTT connection if and when that connection is active. A Session cannot have more than one Non-Shared Subscription with the same Topic Filter, so the Topic Filter can be used as a key to identify the subscription within that Session. If there are multiple clients, each with its own Non-Shared Subscription to the same Topic, each client gets its own copy of the Application Messages that are published on that Topic. This means that Non-Shared Subscriptions cannot be used to load-balance Application Messages across multiple consuming clients as in such cases you would want each message to be delivered to exactly one client. 4.9.2 Shared Subscriptions A Shared Subscription can be associated with multiple subscribing MQTT Sessions. Like a Non-Shared Subscription it has a Topic Filter and a maximum QoS, however a publication that matches its Topic Filter is only sent to one of its subscribing Sessions. This makes it suitable for the load-balancing case. A Shared Subscription is identified using a special style of Topic Filter. The format of this filter is: $share/ {ShareName}/{filter} - $share is a literal string that marks the Topic Filter as being a Shared Subscription Topic Filter. - {ShareName} is a character string that does not include "/", "+" or "#" {filter} The remainder of the string has the same syntax and semantics as a Topic Filter in a non-shared subscription - see section 4.7 A Shared Subscription's Topic Filter MUST start with $share/ and MUST contain a ShareName that is at least one character long. The ShareName MUST NOT contain the characters "/", "+" or "#", but MUST be followed by a "/" character. This "/" character MUST be followed by a Topic Filter as described in section 4.7. Non-normative comment Shared Subscriptions are defined at the level of the MQTT server, rather than at the level of an individual Session. A ShareName is included in the Shared Subscription's Topic Filter so that there can be more than one Shared Subscription on a server that has the same {filter} component. An application could choose to use the ShareName to represent the group of subscribing Sessions that are sharing the subscription, but it is not obliged to do this. Examples: 1. Shared subscriptions "$share/consumer1/sport/tennis/ " and "$share/consumer2/sport/tennis/ " are distinct shared subscriptions and so can be associated with different groups of Sessions. Both of them match the same topics as a non-shared subscription to sport/tennis/+ . If a message were to be published that matches sport/tennis/+ then a copy would be sent to exactly one of the Sessions subscribed to $share/consumer1/sport/tennis/+ , a separate copy of the message would be sent to exactly one of the Sessions subscribed to $share/consumer2/sport/tennis/+ and further copies would be sent to any clients with non-shared subscriptions to sport/tennis/+ 2. Shared subscription "$share/consumer1//finance" matches the same topics as a non-shared subscription to /finance. Note that "$share/consumer1//finance" and "$share/consumer1/sport/tennis/+" are distinct shared subscriptions, even though they have the same ShareName. While they might be related in some way, no specific relationship between them is implied them having the same ShareName. A Shared Subscription is created by using a Shared Subscription Topic Filter in a SUBSCRIBE request. So long as only one Session subscribes to a particular Shared Subscription, the shared subscription behaves like a non-shared subscription, except that i) The $share and {ShareName} portions of the Topic Filter are not taken into account when matching against publications. ii) No Retained Messages are sent to the Session when it first subscribes. It will be sent other matching messages as they are published. Once a Shared Subscription is in existence it is possible for further Sessions to submit a SUBSCRIBE request with the same Shared Subscription Topic Filter. These additional Sessions could either come from different clients or from different connections from the same client. If the server authorizes an additional SUBSCRIBE request, the new Session gets associated with the Shared Subscription as an additional subscriber. Retained messages are not sent to this new subscriber. Each subsequent Application Message that matches the Shared Subscription is now sent to one and only one of the Sessions that are subscribed to the Shared Subscription. A Session can explicitly detach itself from a Shared Subscription by sending an UNSUBSCRIBE packet that contains the full Shared Subscription Topic Filter. Sessions also get detached from their Shared Subscriptions when they terminate. A Shared Subscription lasts for as long as it is associated with at least one Session (i.e. a Session that has issued a successful SUBSCRIBE request to its Topic Filter and that has not completed a corresponding UNSUBSCRIBE). A Shared Subscription survives when the Session that originally created it unsubscribes, unless there are no other Sessions left when this happens. A Shared Subscription ends, and any undelivered messages associated with it are deleted, when there are no longer any Sessions subscribed to it. Further notes on Shared Subscriptions 1. If there's more than one Session subscribed to the Shared Subscription, the server implementation is free to choose, on a message by message basis, which Session to use and what criteria it uses to make this selection. 2. Different subscribing clients are permitted to ask for different Requested QoS levels in their SUBSCRIBE request packets. The server decides which Maximum QoS to grant to each client, and it is permitted to grant different Maximum QoS levels to different subscribers. When sending an Application Message to a client, the server MUST respect the granted QoS for the client's subscription, in the same that it does when sending a message to a Non-Shared Subscriber. 3. If the server is in the process of sending a QoS 2 message to its chosen subscribing client and the connection to that client breaks before delivery is complete the Server MUST complete the delivery of the message to that client when it reconnects as described in section 4.3.3. If the client's Session terminates before the client reconnects, the Server MUST NOT send the Application Message to any other subscribed client. 4. If the Server is in the process of sending a QoS 1 message to its chosen subscribing client and the connection to that client breaks before the Server has received an acknowledgement from the client, the Server MAY wait for the client to reconnect and retransmit the message to that client when that happens. If the client's Session terminates before the client reconnects, the Server SHOULD send the Application Message to another client that is subscribed to the same Shared Subscription. It MAY attempt to send the message to another client as soon as it loses its connection to the first client. 5. If a client responds with a negative acknowledgement to a PUBLISH packet from the Server, the Server MUST discard the Application Message and not attempt to send it to any other Subscriber. 6. A client is permitted to submit a second SUBSCRIBE request to a Shared Subscription on a Session that's already subscribed to that Shared Subscription - it might for example do this in order to change the Requested QoS for its subscription. This does not increase the number of times that that Session is associated with the Shared Subscription, so the Session will leave the Shared Subscription on its first UNSUBSCRIBE. 7. Each Shared Subscription is independent from any other. It is possible to have two Shared Subscriptions with overlapping filters. In such cases a message that matches both Shared Subscriptions will be processed separately by both of them. If a client has a Shared Subscription and a Non-Shared subscription and a message matches both of them, the client will receive a copy of the message by virtue of it having the Non-Shared Subscription. A second copy of the message will be delivered to one of the subscribers to the Shared Subscription, and this could result in a second copy being sent to this client. F. Add new sentence to 5.4.2 Authorization of Clients by the Server An implementation should provide access controls that take place after CONNECT to restrict the client's ability to subscribe to a Shared Subscription. - {filter} The remainder of the string has the same syntax and semantics as a Topic Filter in a non-shared subscription - see section 4.7
Shared Subscriptions
--------------------
Shared subscriptions allow a set of clients to share the consumption of messages
produced in response to a subscription. The set of subscribers is created by the use
of a common share name. Shared subscriptions provide a facility similar to point to
point messaging in that the processing of messages is not limited to the availability
or capacity of a single consumer, the share name is analogous to the queue name in
that it names the list of messages to be processed.
I suggest that a shared subscription be defined by the topic filter syntax:
$share:shareName:topicFilter
- This specialised topic filter takes the place of the normal topic filter in the
subscribe packet. - The "$share:" prefix uses a reserved $ name and will therefore not cause a conflict
with other topic filters. - shareName is a string which labels the shared subscription and must not contain any
":" characters. - TopicFilter follows the existing topic filter rules.
- Subscribing clients will be a member of the share only if both the shareName and
topicFilter are identical. So, a different shareName with the same topicFiler
will create a different share. Similarly a shareName followed by a different topic
filter will create separate share. - Servers may decline to support shared subscriptions by not accepting subscribe
packets containing topic filters starting with the "$share:" prefix. However, if
they do accept the "$share:" prefix they must follow this definition. - The subscribing clients may make both non durable and durable subscriptions by
setting clean session true or false. The shared subscription ceases to exist if
the number of clients subscribed to it reaches zero. If the shared subscription
ceases to exist the messages queued for processing are deleted by the server as
with an non shared subscription. - A good server implementation will avoid allocating messages to subscribers with
durable subscriptions while the client is disconnected. Instead the messages will be
allocated when a suitable client connects. - A Qos=1 message should be reallocated to another client sharing the same subscription
if the network connection to the client is lost before the PUBACK is received.
Qos=0 and Qos=2 messages must not be reallocated.