跳到主要内容

治理与配额

DeviceChain 为所有租户运行一组共享服务。共享实例上的租户隔离关注正确性:一个租户绝不能看到另一个租户的数据。治理关注公平性。每租户配额防止某个租户的突发流量、重连风暴或错误配置的规则耗尽所有租户共享的容量。只隔离数据而不公平分配资源,仍会让一个设备群影响所有人;治理补上这一缺口。

限制在流量到达共享基础设施之前、在边界处执行:

  • 接入。 所有设备传输(HTTP、MQTT、LwM2M 和 Sparkplug)都在设备流量发布到内部流水线前,执行按读数计数的每租户速率限制,每个读数对应一个存储值。对于 HTTP、MQTT 和 LwM2M,每条消息还会在解码前按相同限额计数一次。超过限制的流量在入口被削减,不会堆积到共享消息流。参见默认允许多少。
  • 出站。 动作产生的出站流量,在传递两端都按租户限制速率。检测引擎在派发前削减超预算输出,outbound-connectors 服务在有限预算内接受目标投递流量。两端都根据触发动作的遥测到达平台的时间计量,因此重启后排空的积压按其发生时间计量。
  • AI 推理。 可选 AI 服务执行每租户速率限制,防止某个租户的编写会话独占共享推理路径。可以观察推理费用:提供方报告的输入和输出令牌计为实例级指标,供运维人员观察并配置告警。费用不按租户跟踪,也没有对应预算限制。这里约束租户的只有速率上限。
  • 未投递命令。 每租户上限限制同时等待发出的命令数量,在命令入队时执行。这是此处唯一拒绝而不是削减的限制。前三项会丢弃超额流量;这一项返回调用方可见、可以重试的拒绝,因为命令会产生物理动作,不能静默丢弃。参见租户可以保留多少积压。

每个执行点都通过平台核心中的共享治理库解析限制,使用统一的每租户限制获取器和解析器。因此,各个维度以相同方式回答“该租户允许多少”。

安全回退规则​

治理的其他部分依赖以下安全属性:

缺失或为零的限制解析为平台默认值,绝不表示无限制。

任何配置状态和故障模式都不会让租户失去治理。没有显式限制的租户使用平台默认上限,将限制设为零也表示同样含义,而不是“无限制”。设计不允许失败时放行,即拼写错误或缺失数据行不能静默移除上限。租户数据作用域在正确性方面采取同样立场:没有租户时拒绝查询。

尚未获知租户上限时​

服务从控制平面获取租户上限并缓存。在读取前,它按平台默认值计量租户。服务启动后首次遇到租户时,以及控制平面持续无法访问期间,都会发生这种情况。默认值仍是上限,绝不是无限制。但如果租户层级设定更低上限,在读取成功前,会接受超过该层级允许的流量。已读取过上限的租户,在故障期间继续使用最后已知值。

每个执行限制的服务都会通过 devicechain_<service>_governance_unresolved_admissions_total 统计这种方式接受的流量,按维度和原因标记:

  • unreachable:无法询问控制平面;
  • unknown-tenant:控制平面答复该租户不存在;
  • pending:尚未收到答复。

只有当 unreachable 持续增长 15 分钟时,才触发 TenantsMeteredAtPlatformDefault 告警。

无法确认的租户名称​

HTTP 接入端点在检查设备凭据前,从请求路径取得租户。因此,HTTP 接入为每个租户提供独立额度,与租户 MQTT、NATS 和消息代理在线状态流量使用的额度分开。指定租户的 HTTP 请求不能耗尽该租户的设备流量额度。

不过,能够访问 HTTP 端口且知道租户名称的人,仍能耗尽该租户的 HTTP 额度,因为设备凭据是在请求获准后才检查。额度按读数计数,请求中的读数在检查凭据前扣除,因此只需少量请求:平台默认值下,每秒约四个、每个包含 256 条读数的请求就足够。在 HTTP 额度内,只有经控制平面确认的租户名称,或固定集合中的名称,才能获得独立额度;该集合最多 1024 个名称。超出后,所有这些名称共享一个平台默认额度,并触发 RateLimiterOverflowInUse 告警。

该集合限制服务内存,而不是虚构名称的总接入量:这些名称合计最多可以接受平台默认值的 1024 倍。

MQTT、NATS 和 LwM2M 流量来自经过认证或运维人员选择信任的来源,始终获得独立额度:

  • 平台消息代理认证每台设备;
  • LwM2M 检查设备密钥;
  • 外部 MQTT 消息代理来源由运维人员配置,因此被信任。

限制保存在哪里​

治理限制是运维和租户配置,不是客户端输入:

  • 声明在租户控制平面记录中,通过管理控制台和控制平面 API 编辑。
  • 绝不是令牌声明。 调用方 JWT 标识租户,执行限制的服务随后从配置解析该租户限制。客户端发送的任何内容——标头、声明、载荷——都无法提高自身上限。

层级提供上限​

租户治理上限来自其**层级**。这是运维人员定义的服务组合实体,回答“这是哪类客户”。层级用于组合数量,即一类租户继承的默认上限。解析遵循三级回退:

租户专属覆盖值 → 层级设置 → 平台默认值

租户专属覆盖值是经过审计的例外,不是主要机制。层级提供服务组合中的答案,平台默认值则是安全回退规则保证的基础值。

AI 模型使用资格采用相同回退:先使用租户模型分配,再使用租户层级标记的默认模型。因此,“该租户在哪个层级”在治理和 AI 中具有一致含义。租户品牌也级联,但没有层级这一层:租户覆盖值,然后是运维人员的 branding.default 系统设置,最后是内置默认值。

上限按副本计算​

每个运行中的服务副本独立执行本页所有速率上限,副本之间不协调。如果 event-sources、outbound-connectors 或 ai-inference 有两个副本并分担租户流量,该租户最多可获准达到上限的两倍,N 个副本则最多 N 倍。默认安装每项服务运行一个副本,因此上限只应用一次,但滚动更新期间新旧 Pod 同时运行的短暂阶段除外。

两种上限不会成倍增加:

  • 未投递命令上限是保存在数据库中的计数;
  • 检测引擎的出站上限只在进行检测的副本上计量。

横向扩展服务时,请根据实际副本数量设置层级上限。

接入何时可以超过租户上限​

在单个 event-sources 副本中,租户接入上限分别应用于三个额度,而非租户整体:

  • 实时流量:租户设备当前通过 MQTT 和 NATS 发送的流量,包括消息代理在线状态。
  • 积压:event-sources 停机或处理落后时,平台消息代理存储的消息,排空时按其发送时间计量。租户在故障后同时排空积压并发送实时流量时,在追平之前最多可达到上限两倍。
  • HTTP 接入:单独计量,因此同时使用 HTTP 和 MQTT 的租户可以在两者上各达到上限。

因此,event-sources 内每个副本最多允许租户达到上限三倍,再按上述副本数倍增。LwM2M 和 Sparkplug 各自使用独立额度,因此两者都运行时,最坏情况为上限五倍。

默认允许多少​

平台默认值为每租户每秒 1000 条读数,突发额度为 2000。读数是一个存储值:测量条目中的一个键、一个位置或一条警报。携带 256 条读数的消息消耗 256 额度。

在三个专用 4-vCPU/16 GB 数据库节点和三个 4-vCPU/8 GB 服务节点组成的集群上,默认高可用安装使用一个 event-sources 副本、两个 event-management Pod,实测连续 10 分钟存储每秒 6,000 条读数。默认设置下,即使同时排空积压并运行两项边缘服务,单个租户自身设备最多获准达到 1000 的五倍,即每秒 5,000 条读数,低于该实测值。不排空积压且不运行边缘服务时,为 2,000。

这不是所有环境中的保证:

  • 较小集群的存储能力更低,应降低默认值。
  • 多个 event-sources 副本,以及滚动更新中新旧 Pod 同时运行,都会放大上限。
  • 层级提高上限的租户可以发送更多。
  • 所有租户合计仍可能超过安装的存储能力。此时,共享背压检查会拒绝所有租户。
  • HTTP 接入在检查任何凭据前指定租户,因此发送者可以使用不存在的租户名称。这些名称各自按平台默认值计量,大量名称合计仍能触发关闭接入。

观察治理效果​

削减流量作为运维指标报告。运维人员可以在问题变成支持请求之前,发现达到上限的租户或开始过量输出的规则。治理应表现为可观察的压力,而不是静默丢失。

状态

**目前已执行:**每租户接入速率限制(event-sources)、动作传递两端的出站治理(event-processing 和 outbound-connectors)、带费用可观测性的每租户 AI 推理速率限制,以及每租户未投递命令上限(command-delivery)。全部遵循上述安全回退规则。

**计划采用同一模型:**每租户 API/查询治理、内部消息总线的每租户流容量限制,以及关系扇出上限。

  • 多租户:正确性方面,在同一共享实例中拒绝无作用域查询的数据隔离。
  • 出站连接器:出站治理如何应用于 webhook 和消息代理发布。
  • 租户层级:提供租户默认上限的服务组合实体。