From bcc79e34e79114277a62790d4be2fdda684697e6 Mon Sep 17 00:00:00 2001 From: Meggielqk <126552073+Meggielqk@users.noreply.github.com> Date: Fri, 21 Nov 2025 14:55:17 +0800 Subject: [PATCH 1/2] update(shared subscription): Add dispatch strategy --- en_US/messaging/mqtt-shared-subscription.md | 40 ++++++++++++++++++++- zh_CN/messaging/mqtt-shared-subscription.md | 38 ++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/en_US/messaging/mqtt-shared-subscription.md b/en_US/messaging/mqtt-shared-subscription.md index 9e648c5be..d10b9deb2 100644 --- a/en_US/messaging/mqtt-shared-subscription.md +++ b/en_US/messaging/mqtt-shared-subscription.md @@ -13,7 +13,7 @@ You can use client tools to connect to EMQX and try this messaging service. This ## Shared Subscription for Groups -You can enable a shared subscription for groups of subscribers by adding the prefixed `$share/` to the original topic. The group name can be any string. EMQX forwards messages to different groups at the same time and subscribers belonging to the same group receive messages with load balancing. +You can enable a shared subscription for groups of subscribers by adding the prefixed `$share/` to the original topic. The group name can be any string. EMQX forwards messages to different groups at the same time, and subscribers belonging to the same group receive messages with load balancing. For example, if subscribers `s1`, `s2`, and `s3` are members of group `g1`, subscribers `s4` and `s5` are members of group `g2`, and all subscribers subscribe to the original topic `t1`. The shared subscription topics must be `$share/g1/t1` and `$share/g2/t1`. When EMQX publishes a message `msg1` to the original topic `t1`: @@ -37,6 +37,44 @@ When clients use MQTT v5, it is a good practice to set a short session expiry in For more information on the persistent session, see [MQTT Persistent Session and Clean Session Explained](https://www.emqx.com/en/blog/mqtt-session). +## Configure Shared Subscription Strategy + +EMQX allows fine-grained control over how messages are distributed to subscribers within a shared subscription group. This behavior is defined by the Shared Subscription Strategy, which determines the algorithm used to select the subscriber that receives each message. By tuning this strategy, you can optimize message flow for different workloads, client deployment patterns, and cluster topologies. + +### Shared Subscription Dispatch Strategy + +The shared subscription dispatcher supports multiple strategies that influence how EMQX balances messages among subscribers: + +- **`random`**: Selects a subscriber at random, providing evenly distributed but non-deterministic message routing. + +- **`round_robin`**: Circulates messages through subscribers in sequence to achieve predictable distribution. + +- **`round_robin_per_group`**: Applies round-robin selection independently within each shared subscription group, suitable for deployments where groups represent separate workloads. + +- **`sticky`**: Attempts to keep routing messages to the same subscriber until the subscriber disconnects. This strategy helps avoid unnecessary re-processing or cross-client state sharing by keeping message flows on a single subscriber whenever possible. + + When using this strategy, EMQX also applies an **Initial Sticky Pick** rule to decide which subscriber becomes the initial target when no sticky association exists. + +- **`local`**, **`hash_topic`**, **`hash_clientid`**: These strategies apply deterministic routing rules. The `local` strategy prioritizes delivering messages to subscribers on the same cluster node where the message is processed, reducing cross-node traffic and latency. The `hash_topic` and `hash_clientid` strategies use hashing on the topic name or publisher Client ID to route messages consistently to a specific subscriber. These strategies are useful when messages need stable, predictable routing for stateful processing or sharding scenarios. + +### Initial Sticky Pick + +When the shared subscription strategy is set to `sticky`, EMQX must determine the first subscriber to associate with the incoming message flow. The **Shared Subscription Initial Sticky Pick** option defines how EMQX performs this initial selection. + +This allows you to control whether the system favors local subscribers, uses hashing for deterministic routing, or randomly selects a subscriber. + +### Configure Dispatch Strategy via Dashboard + +You can configure these options in the EMQX Dashboard: + +1. Navigate to **Management** -> **MQTT Settings** -> **General**. +2. Ensure **Allowed Shared Subscription** is enabled. +3. Select the desired **Shared Subscription Strategy** from the dropdown list. The default option is `round_robin`. +4. If the selected strategy is `sticky`, choose an appropriate **Shared Subscription Initial Sticky Pick** method. The default option is `random`. +5. Click **Save Changes**. + +These settings take effect immediately and allow EMQX to adjust its message dispatching logic without requiring client-side configuration changes. + ## Try Shared Subscription with MQTTX Desktop :::tip Prerequisites diff --git a/zh_CN/messaging/mqtt-shared-subscription.md b/zh_CN/messaging/mqtt-shared-subscription.md index d21becfda..629786a87 100644 --- a/zh_CN/messaging/mqtt-shared-subscription.md +++ b/zh_CN/messaging/mqtt-shared-subscription.md @@ -35,6 +35,44 @@ EMQX 实现了 MQTT 的共享订阅功能。共享订阅是一种订阅模式, 更多关于持久会话功能的信息,参阅 [MQTT 持久会话与 Clean Session 详解](https://www.emqx.com/zh/blog/mqtt-session)。 +## 配置共享订阅策略 + +EMQX 允许对共享订阅组内消息的分发方式进行精细控制。共享订阅策略用于定义 EMQX 在多个订阅者之间选择消息接收者所采用的算法。通过调整该策略,您可以根据不同的工作负载、客户端部署模式以及集群拓扑来优化消息流转效果。 + +### 共享订阅调度策略 + +共享订阅调度器支持多种策略,用于影响 EMQX 在订阅者之间的负载均衡方式: + +- **`random`**:随机选择一个订阅者,实现均匀但不可预测的消息分发。 + +- **`round_robin`**:以轮询方式依次将消息分发给订阅者,实现可预期的分发顺序。 + +- **`round_robin_per_group`**:在每个共享订阅组内独立地执行轮询分发,适用于不同组代表不同业务场景的部署方式。 + +- **`sticky`**:在订阅者未断开前,尽可能持续将消息路由到同一个订阅者。此策略可避免重复处理或在不同订阅者之间共享状态,使相关消息尽可能保持在同一订阅者上处理。 + + 当使用此策略时,EMQX 会使用**初始 Sticky 选择策略**,在没有现存粘性关联时决定首个目标订阅者。 + +- **`local`**、**`hash_topic`**、**`hash_clientid`**:这些策略采用确定性路由规则。`local` 策略优先将消息发送给当前处理消息的集群节点上的本地订阅者,从而减少跨节点流量和延迟。`hash_topic` 和 `hash_clientid` 策略则基于主题名称或发布客户端 ID 的哈希值进行路由,使消息稳定一致地分配到特定订阅者。这些策略适用于需要稳定、可预测路由的状态化处理或分片(sharding)场景。 + +### 初始 Sticky 选择策略 + +当共享订阅策略设置为 `sticky` 时,EMQX 需要确定应将首次消息流关联到哪个订阅者。**初始 Sticky 选择策略**选项用于定义 EMQX 执行该初始选择的方式。 + +该选项允许您控制系统是优先选择本地订阅者、使用哈希算法进行确定性选择,还是随机选择订阅者。 + +### 通过 Dashboard 配置策略 + +您可以通过 EMQX Dashboard 配置这些策略: + +1. 导航至 **管理** -> **MQTT 配置** -> **通用**。 +2. 确保**允许共享订阅**已启用。 +3. 从下拉列表中选择所需的**共享订阅策略**。默认为 `round_robin`。 +4. 如果选择了 `sticky`,需配置合适的**共享订阅初始 Sticky 选择策略**。默认为 `random`。 +5. 点击**保存修改**。 + +这些设置会立即生效,使 EMQX 能够调整消息调度逻辑,而无需客户端进行任何额外配置。 + ## 使用 MQTTX Desktop 尝试共享订阅 :::tip 前置准备 From 5983170a7017434d7a32d6a08fec0d88cedd64e8 Mon Sep 17 00:00:00 2001 From: Meggielqk <126552073+Meggielqk@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:05:19 +0800 Subject: [PATCH 2/2] Update dispatch strategy descriptions --- dir.yaml | 4 ++-- en_US/messaging/mqtt-shared-subscription.md | 26 +++++++++++---------- zh_CN/messaging/mqtt-shared-subscription.md | 26 +++++++++++---------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/dir.yaml b/dir.yaml index b496445bc..912b594c9 100644 --- a/dir.yaml +++ b/dir.yaml @@ -835,8 +835,8 @@ title_cn: 版本发布历史 collapsed: true children: - - title_en: EMQX Enterprise Release Notes - title_cn: EMQX 企业版版本发布历史 + - title_en: Release Notes + title_cn: 版本发布历史 collapsed: true path: changes/all-changes-ee children: diff --git a/en_US/messaging/mqtt-shared-subscription.md b/en_US/messaging/mqtt-shared-subscription.md index d10b9deb2..18d9c73e1 100644 --- a/en_US/messaging/mqtt-shared-subscription.md +++ b/en_US/messaging/mqtt-shared-subscription.md @@ -43,25 +43,27 @@ EMQX allows fine-grained control over how messages are distributed to subscriber ### Shared Subscription Dispatch Strategy -The shared subscription dispatcher supports multiple strategies that influence how EMQX balances messages among subscribers: +The Shared Subscription Dispatch Strategy determines how EMQX distributes messages among subscribers within a shared subscription group. -- **`random`**: Selects a subscriber at random, providing evenly distributed but non-deterministic message routing. +You can configure this using the `mqtt.shared_subscription_strategy` option. -- **`round_robin`**: Circulates messages through subscribers in sequence to achieve predictable distribution. +| Strategy | Description | +| --------------------------- | ------------------------------------------------------------ | +| **`random`** | Randomly selects one subscriber in the group for each message. This provides even distribution overall but may not be deterministic. | +| **`round_robin`** (default) | Messages are delivered to subscribers in turn within each shared subscription group. EMQX maintains a separate round-robin position for each publishing client, so messages from different publishers may still be delivered to the same subscriber consecutively. | +| **`round_robin_per_group`** | Similar to `round_robin`, but the round-robin progress is tracked independently on each node. This means messages published from different nodes in a cluster may be delivered to the same subscriber. Useful for clustered deployments where each node handles separate publisher loads. | +| **`sticky`** | Continuously dispatches messages to the same subscriber until the subscriber disconnects or its session ends. This strategy helps avoid unnecessary re-processing or cross-client state sharing by keeping message flows on a single subscriber whenever possible.
The initial subscriber is determined by the `mqtt.shared_subscription_initial_sticky_pick` setting. | +| **`local`** | Prefers delivering messages to subscribers connected to the same node where the message is processed. If no local subscribers exist, EMQX randomly selects a subscriber from the cluster. This reduces inter-node traffic and latency. | +| **`hash_clientid`** | Uses a hash of the publisher’s Client ID to consistently route all messages from that publisher to the same subscriber. This strategy provides deterministic routing for per-client data streams. | +| **`hash_topic`** | Uses a hash of the publishing topic to route all messages with the same topic name to the same subscriber. Useful for topic-based message sharding and stateful processing. | -- **`round_robin_per_group`**: Applies round-robin selection independently within each shared subscription group, suitable for deployments where groups represent separate workloads. - -- **`sticky`**: Attempts to keep routing messages to the same subscriber until the subscriber disconnects. This strategy helps avoid unnecessary re-processing or cross-client state sharing by keeping message flows on a single subscriber whenever possible. - - When using this strategy, EMQX also applies an **Initial Sticky Pick** rule to decide which subscriber becomes the initial target when no sticky association exists. - -- **`local`**, **`hash_topic`**, **`hash_clientid`**: These strategies apply deterministic routing rules. The `local` strategy prioritizes delivering messages to subscribers on the same cluster node where the message is processed, reducing cross-node traffic and latency. The `hash_topic` and `hash_clientid` strategies use hashing on the topic name or publisher Client ID to route messages consistently to a specific subscriber. These strategies are useful when messages need stable, predictable routing for stateful processing or sharding scenarios. +> EMQX tracks dispatch state, such as round-robin positions or sticky subscriber assignments, per publisher connection. When a publishing client disconnects and reconnects, this state is reset and reinitialized. ### Initial Sticky Pick -When the shared subscription strategy is set to `sticky`, EMQX must determine the first subscriber to associate with the incoming message flow. The **Shared Subscription Initial Sticky Pick** option defines how EMQX performs this initial selection. +When the shared subscription strategy is set to `sticky`, EMQX determines the initial subscriber to receive the messages based on `mqtt.shared_subscription_initial_sticky_pick`. -This allows you to control whether the system favors local subscribers, uses hashing for deterministic routing, or randomly selects a subscriber. +This setting controls whether EMQX prefers local subscribers, uses hashing for deterministic routing, or selects randomly. ### Configure Dispatch Strategy via Dashboard diff --git a/zh_CN/messaging/mqtt-shared-subscription.md b/zh_CN/messaging/mqtt-shared-subscription.md index 629786a87..deee38164 100644 --- a/zh_CN/messaging/mqtt-shared-subscription.md +++ b/zh_CN/messaging/mqtt-shared-subscription.md @@ -41,25 +41,27 @@ EMQX 允许对共享订阅组内消息的分发方式进行精细控制。共享 ### 共享订阅调度策略 -共享订阅调度器支持多种策略,用于影响 EMQX 在订阅者之间的负载均衡方式: +共享订阅调度策略定义了 EMQX 在共享订阅组中如何选择具体的订阅者来接收消息。 -- **`random`**:随机选择一个订阅者,实现均匀但不可预测的消息分发。 +您可以通过配置项 `mqtt.shared_subscription_strategy` 来设置该策略。 -- **`round_robin`**:以轮询方式依次将消息分发给订阅者,实现可预期的分发顺序。 +| 策略 | 说明 | +| --------------------------- | ------------------------------------------------------------ | +| **`random`** | 在每次消息分发时,从共享订阅组内随机选择一个订阅者,实现整体上较为均匀但不可预测的消息分发。 | +| **`round_robin`**(默认) | 在共享订阅组内按顺序轮询将消息分发给订阅者。EMQX 为每个发布客户端独立维护轮询进度,因此来自不同发布者的消息可能连续被投递到同一个订阅者。 | +| **`round_robin_per_group`** | 与 `round_robin` 类似,但轮询进度在每个节点上独立维护。这意味着来自集群中不同节点的消息可能仍会被投递到同一个订阅者。该策略适用于多节点集群场景,每个节点可独立处理部分发布者负载。 | +| **`sticky`** | 在订阅者保持连接的情况下,消息会持续分发到同一个订阅者,直到该订阅者断开连接或会话结束。此策略通过将消息流保持在单一订阅者上,避免重复处理或跨订阅者共享状态。
首次选择的订阅者由配置项 `mqtt.shared_subscription_initial_sticky_pick` 决定。 | +| **`local`** | 优先将消息分发给当前节点上的本地订阅者。如果没有本地订阅者,EMQX 将随机选择集群中其他节点的订阅者,从而降低跨节点流量与延迟。 | +| **`hash_clientid`** | 基于发布客户端的 Client ID 计算哈希值,将同一发布者的所有消息始终路由到同一个订阅者,实现确定性、稳定的消息路由。该策略适用于按客户端维度进行有状态处理的场景。 | +| **`hash_topic`** | 基于发布主题名称计算哈希值,将相同主题的所有消息路由到同一个订阅者。该策略适用于基于主题分片(sharding)或需要稳定消息处理的场景。 | -- **`round_robin_per_group`**:在每个共享订阅组内独立地执行轮询分发,适用于不同组代表不同业务场景的部署方式。 - -- **`sticky`**:在订阅者未断开前,尽可能持续将消息路由到同一个订阅者。此策略可避免重复处理或在不同订阅者之间共享状态,使相关消息尽可能保持在同一订阅者上处理。 - - 当使用此策略时,EMQX 会使用**初始 Sticky 选择策略**,在没有现存粘性关联时决定首个目标订阅者。 - -- **`local`**、**`hash_topic`**、**`hash_clientid`**:这些策略采用确定性路由规则。`local` 策略优先将消息发送给当前处理消息的集群节点上的本地订阅者,从而减少跨节点流量和延迟。`hash_topic` 和 `hash_clientid` 策略则基于主题名称或发布客户端 ID 的哈希值进行路由,使消息稳定一致地分配到特定订阅者。这些策略适用于需要稳定、可预测路由的状态化处理或分片(sharding)场景。 +> EMQX 会为每个发布客户端独立维护分发状态(例如轮询进度或 Sticky 订阅者分配情况)。当发布客户端断开并重新连接后,该状态会被重置并重新初始化,消息分发将重新开始。 ### 初始 Sticky 选择策略 -当共享订阅策略设置为 `sticky` 时,EMQX 需要确定应将首次消息流关联到哪个订阅者。**初始 Sticky 选择策略**选项用于定义 EMQX 执行该初始选择的方式。 +当共享订阅策略设置为 `sticky` 时,EMQX 需要确定应将首次消息流关联到哪个订阅者。EMQX 会根据配置项 `mqtt.shared_subscription_initial_sticky_pick` 来确定首次接收消息的订阅者。 -该选项允许您控制系统是优先选择本地订阅者、使用哈希算法进行确定性选择,还是随机选择订阅者。 +该设置可控制 EMQX 是优先选择本地订阅者、基于哈希算法进行确定性选择,还是随机选择订阅者。 ### 通过 Dashboard 配置策略