全局命名空间设置
在 EMQX 6.1 中,除了可以对单个命名空间实例进行配置外,还提供了一组全局命名空间设置,用于控制命名空间的识别方式、隔离行为以及与主题和授权相关的处理逻辑。
这些设置作用于整个集群,并对所有命名空间和客户端连接生效,通常需要在启用和使用命名空间功能之前进行配置。
全局命名空间设置可通过 Dashboard 进行管理,路径为:管理 -> 命名空间 -> 设置。
提示
为保持向后兼容性,EMQX 6.1 中的大多数全局命名空间设置(如客户端 ID 隔离、将命名空间作为主题挂载点、授权检查包含挂载点)默认均为关闭状态。
如需启用相应的隔离能力,请在命名空间相关配置中显式开启相关配置。

仅允许显示创建的命名空间
该配置用于控制客户端是否只能连接到已显式创建的命名空间,在配置文件中对应 multi_tenancy.allow_only_managed_namespaces。
当启用该配置时,EMQX 会在客户端连接阶段对命名空间进行校验,并据此决定是否允许连接。
- 启用:
- 如果客户端所属的命名空间不是通过 Dashboard 或 REST API 显式创建的,该客户端将被拒绝连接。
- 如果客户端的命名空间无法解析(例如未配置命名空间来源,或命名空间来源规则未生成有效值),该客户端也将被拒绝连接。
- 关闭:
- 允许客户端连接到未显式创建的命名空间。
- 在满足命名空间来源规则的前提下,EMQX 可根据需要自动创建命名空间。
提示
启用该配置前,请确保已正确配置命名空间来源,并且所有合法客户端都能够解析出已显式创建的命名空间。否则,客户端可能因无法解析命名空间或命名空间尚未显式创建而被拒绝连接。
当命名空间解析时机设置为认证后时,认证前的命名空间校验将被跳过,对显式创建命名空间的检查将在认证完成后执行。
默认最大会话数
该配置用于为新创建的命名空间设置默认的最大会话数上限。
- 启用:新创建的命名空间将自动继承该最大会话数限制。
- 关闭:新创建的命名空间默认不限制最大会话数(
infinity)。
该配置仅对新创建的命名空间生效,不会影响已经存在的命名空间。已存在命名空间的最大会话数需在对应命名空间的配置中单独修改。
禁止使用的命名空间名称
从 EMQX 6.3.0 开始,multi_tenancy.deny_namespaces 用于指定不能用作命名空间标识的名称。该限制适用于 Dashboard 用户角色、API 密钥、通过管理 API 创建和批量导入命名空间,以及通过 client_attrs.tns 为客户端分配命名空间。
默认列表为 ["global", "undefined", "null", "none"]。这些名称在日志和 Dashboard 输出中容易与内部标识混淆。
在 Dashboard 中编辑该列表:
- 进入管理 -> 命名空间 -> 设置。
- 在禁止使用的命名空间名称中,按需添加或移除名称。清空所有条目可关闭名称限制。
- 点击确定应用更改。
您也可以在 etc/base.hocon 中配置该列表。以下示例使用默认值:
multi_tenancy.deny_namespaces = ["global", "undefined", "null", "none"]自定义列表会替换默认列表。如果仍需禁止某些默认名称,请将其保留在列表中。设置 multi_tenancy.deny_namespaces = [] 可关闭名称限制。配置文件的优先级请参见配置覆盖规则。
如果客户端解析出的命名空间在该列表中,EMQX 将拒绝连接并返回 not_authorized,即使已关闭仅允许显式创建的命名空间也是如此。当 multi_tenancy.allow_only_managed_namespaces = false 时,该名称限制不会阻止未分配命名空间的客户端连接。
重要提示
默认列表会禁止使用 EMQX 6.3.0 之前允许的名称。EMQX 不会自动迁移使用这些名称的命名空间。升级前,请更换受影响的命名空间名称,或调整 multi_tenancy.deny_namespaces 以允许使用这些名称。
命名空间解析时机
该设置控制 EMQX 在连接生命周期的哪个阶段解析客户端的命名空间标识。
EMQX 支持两种模式,可在 Dashboard 中通过命名空间解析时机单选按钮进行选择:
- 认证前(默认):在认证链执行前,使用当时可用的连接元数据(如
username、clientid、cert_common_name等)对命名空间表达式进行求值。在配置文件中,对应通过mqtt.client_attrs_init配置tns属性。 - 认证后:在完整的认证链执行完成后,对命名空间表达式进行求值。除标准连接元数据外,还可访问
client_attrs.*值,包括认证后端返回的属性(例如,HTTP 认证后端返回的tag字段)。在配置文件中,对应配置multi_tenancy.post_auth_tns_expression。
TIP
若配置了认证后模式,EMQX 将使用认证后表达式分配命名空间。当该表达式求值为空或出错时,不会回退到认证前的 tns 值。详情请参见认证后表达式为空或求值出错。
与"仅允许显式创建的命名空间"的交互
选择认证后模式时,认证前的命名空间检查会被完全跳过,即使已启用仅允许显式创建的命名空间也是如此。所有校验(命名空间是否已存在、配额检查)均推迟到认证完成、最终命名空间值确定后再执行。
命名空间来源
该设置定义 EMQX 用于派生客户端命名空间标识(client_attrs.tns)的 Variform 表达式。
表达式的求值时机由命名空间解析时机设置决定:
- 认证前模式下,仅可使用标准连接元数据:
username、clientid、cert_common_name及其他预认证属性。 - 认证后模式下,还可使用
client_attrs.*,包括认证结果中合并进来的属性。
TIP
命名空间来源规则使用 Variform 表达式进行定义,有关 Variform 表达式的语法和可用函数,请参考 Variform 表达式。
该配置是以下功能的前提条件:
- 自动创建命名空间
- 基于命名空间的主题隔离
- 基于命名空间的客户端 ID 隔离
- 命名空间级会话限制与速率限制
如果未配置命名空间来源,则客户端不会被分配到任何命名空间,相关隔离和控制功能也不会生效。
示例
认证前
从用户名中提取命名空间:
nth(1, tokens(username, '-'))在该配置下,使用用户名 tenantA-user1 连接的客户端,会在认证执行前将 tenantA 赋值为其命名空间标识。
认证后
使用 HTTP 认证后端返回的 tag 属性:
client_attrs.tag带回退(当认证后端未返回 tag 时,回退到 username):
coalesce(client_attrs.tag, username)在该配置下,EMQX 等待认证链执行完毕后,从合并后的 client_attrs 中读取 tag 值,并将其赋值为命名空间标识。
认证后表达式为空或求值出错
配置 multi_tenancy.post_auth_tns_expression 后,如果表达式求值为空字符串或出错,EMQX 将按以下规则处理连接。求值出错时还会记录一条警告日志。
- 如果认证前的
client_attrs.tns值在multi_tenancy.deny_namespaces列表中,EMQX 将拒绝连接并返回not_authorized。 - 否则,EMQX 将客户端视为未分配命名空间:
- 当
multi_tenancy.allow_only_managed_namespaces = true时,EMQX 拒绝连接并返回not_authorized。 - 当
multi_tenancy.allow_only_managed_namespaces = false时,EMQX 清除认证前的tns值(如有),允许客户端以无命名空间状态连接。
- 当
客户端 ID 隔离
客户端 ID 隔离用于解决多租户场景下不同命名空间使用相同客户端 ID 导致冲突的问题。
EMQX 在全局范围内使用有效客户端 ID 标识会话,而不是使用命名空间和客户端 ID 的组合。因此,客户端 ID 隔离通过生成全局唯一的有效客户端 ID 来避免冲突,通常会在原始客户端 ID 前添加命名空间前缀。客户端仍发送原始客户端 ID,EMQX 在内部将覆盖后的 ID 用作有效客户端 ID。
选择客户端 ID 覆盖机制
请根据命名空间信息的来源以及有效客户端 ID 是否必须包含命名空间,选择覆盖机制:
- 如果命名空间在认证前生成,请配置
mqtt.clientid_override。EMQX 在mqtt.client_attrs_init执行完成后、认证开始前对该表达式求值,因此表达式可以使用由mqtt.client_attrs_init初始化的属性,包括client_attrs.tns。 - 如果命名空间来自认证结果,并且有效客户端 ID 必须包含该命名空间,请配置认证后端返回
clientid_override。返回值必须包含完整的新客户端 ID。mqtt.clientid_override表达式无法使用认证后端返回的属性,也无法使用multi_tenancy.post_auth_tns_expression生成的命名空间。 - 如果
multi_tenancy.post_auth_tns_expression设置命名空间,但有效客户端 ID 不需要包含该命名空间,则只有在客户端已使用全局唯一客户端 ID 时,才无需配置客户端 ID 覆盖。
一个连接只应使用一种客户端 ID 覆盖机制。如果同时配置两种机制,认证结果覆盖会在稍后执行,并替换 mqtt.clientid_override 生成的客户端 ID。无论使用哪种机制,都必须确保最终生成的客户端 ID 全局唯一。
EMQX 应用客户端 ID 覆盖的顺序
EMQX 按以下顺序确定有效客户端 ID:
- 通过
mqtt.client_attrs_init初始化客户端属性。 - 在认证前对
mqtt.clientid_override求值。 - 认证客户端,并应用认证成功结果中返回的非空
clientid_override。 - 对
multi_tenancy.post_auth_tns_expression求值。 - 使用有效客户端 ID 打开客户端会话。
EMQX 不会在认证后再次对 mqtt.clientid_override 求值,也不会自动将认证后获取的命名空间添加到客户端 ID。如果认证成功结果中未包含 clientid_override 或其值为空,EMQX 将继续使用此前确定的客户端 ID。
配置认证前客户端 ID 隔离
在 Dashboard 中启用客户端 ID 隔离时,EMQX 会配置 mqtt.clientid_override 并自动填入一个推荐表达式:
concat([client_attrs.tns, '-', clientid])重要提示
从 EMQX 6.3.0 开始,如果 mqtt.clientid_override 表达式求值出错或生成空字符串,EMQX 会记录错误日志并拒绝连接。MQTT 5.0 客户端会收到 CONNACK 原因码 0x85(Client Identifier not valid),MQTT 3.1 和 3.1.1 客户端会收到返回码 2。EMQX 不会回退到客户端提供的 Client ID。
升级前,请确认每个连接的客户端都能将已配置的表达式求值为非空字符串。如果某个客户端无法生成有效结果,请修正表达式或该客户端必需的数据。
在上述配置下:
- 不同命名空间中的客户端即使使用相同的 Client ID,也不会发生冲突。
- 内部实际使用的客户端 ID 将包含命名空间前缀。
该表达式仅作为认证前生成命名空间时的示例。可以根据业务需要调整表达式,但必须确保最终生成的客户端 ID 在全局范围内保持唯一。
实际效果示例
假设已配置命名空间来源,并从用户名中提取命名空间:
nth(1, tokens(username, '-'))并启用了客户端 ID 隔离,使用默认表达式:
concat([client_attrs.tns, '-', clientid])客户端连接信息
| 客户端 | 用户名 | Client ID |
|---|---|---|
| A | tenantA-user1 | client1 |
| B | tenantB-user2 | client1 |
EMQX 内部实际使用的客户端 ID
| 命名空间 | 原 Client ID | 实际 Client ID |
|---|---|---|
| tenantA | client1 | tenantA-client1 |
| tenantB | client1 | tenantB-client1 |
将命名空间作为挂载点
启用该配置后,EMQX 会在成功识别命名空间的前提下,将客户端所属的命名空间作为主题挂载点(mountpoint),用于实现命名空间级别的主题隔离。
如果监听器已单独配置了 mountpoint,则会忽略该设置,以监听器上的 mountpoint 配置为准。
行为说明
启用将命名空间作为挂载点后,EMQX 会通过以下方式对主题进行隔离处理:
- 在客户端执行 PUBLISH、SUBSCRIBE、UNSUBSCRIBE 以及遗嘱消息时:
- EMQX 会在 Broker 内部自动为主题添加命名空间前缀
{namespace}/。
- EMQX 会在 Broker 内部自动为主题添加命名空间前缀
- 在消息投递给客户端时:
- EMQX 会自动移除该命名空间前缀。
- 对客户端而言:
- 发布和订阅的主题名称始终保持不变。
- 客户端无需感知命名空间前缀的存在。
示例说明
假设客户端所属命名空间为 n1,并已启用将命名空间作为挂载点。
客户端侧行为
- 客户端订阅主题:
sensors/# - 客户端发布主题:
sensor/data
EMQX 内部处理过程
- Broker 在内部注册订阅主题:
n1/sensors/# - Broker 在内部路由消息:
n1/sensors/data - 消息最终投递给客户端时:
sensors/data
可以看到:
- 命名空间前缀仅在 EMQX 内部生效。
- 客户端始终使用原始主题名称。
- 不同命名空间的客户端即使使用相同主题,也不会互相收到消息。
授权检查时包含挂载点
该配置用于控制在执行授权(ACL)校验时,目标主题和主题过滤器是否在匹配 ACL 规则或授权器之前,自动加上主题挂载点前缀。
该挂载点前缀通常来自命名空间(当启用“将命名空间作为挂载点”时),其格式为:{namespace}/。
行为说明
启用授权检查时包含挂载点后,EMQX 的授权校验流程将发生如下变化:
- 在执行 ACL 规则或授权器匹配之前,EMQX 会先为目标主题或主题过滤器添加主题挂载点前缀。
- 随后,使用带有挂载点前缀的主题进行授权校验。
该行为适用于以下操作场景:
- PUBLISH
- SUBSCRIBE
- UNSUBSCRIBE
- 遗嘱消息
示例说明
假设已启用以下配置:
- 将命名空间作为挂载点
- 授权检查时包含挂载点
- 客户端所属命名空间为
n1
客户端侧行为
客户端尝试订阅主题:sensors/#。
授权检查时的实际匹配主题
在执行授权校验时,EMQX 使用的主题为:n1/sensors/#。因此,对应的 ACL 规则应配置为:n1/sensors/#,而不是 sensors/#。
使用建议
当启用了将命名空间作为挂载点用于主题隔离时,建议同时启用本配置。这样可以确保授权校验所使用的主题与 Broker 内部实际生效的主题名称保持一致,避免出现授权结果与实际路由行为不一致的情况。
显示自动创建的命名空间(Dashboard 显示行为)
该配置仅影响 Dashboard 中命名空间列表的显示行为,不影响命名空间的创建或实际生效逻辑。
- 启用: Dashboard 仅显示显式创建的命名空间
- 关闭: Dashboard 同时显示显式创建的命名空间和根据命名空间来源规则自动创建的命名空间