关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

MQTT 长连接上到五万设备之后:ThingsBoard 这类 IoT 平台的连接、落库与规则链谁先撑不住

发布时间:2026-10-12

某工业网关项目出过这样一张监控截图:平台那台机器 CPU 长期在 28% 到 35% 之间晃,内存占用 42%,磁盘还剩六成空间,所有常规告警阈值一条都没触发。但现场反馈是"数据上不来"——设备端 publish 返回超时,遥测曲线断成一段一段,报警推送比实际事件发生时间晚了十几分钟。运维先怀疑运营商线路,查了一圈,链路没问题,机房出口也没丢包。真正的断点在平台自己:文件描述符打到上限,新进来的 TCP 连接被直接拒绝;规则引擎的内存队列堆了四十多万条没有消费;时序库那边的批量写入被拆成了单条插入,磁盘 util 已经 98%。

这是长连接型物联网平台最容易被误判的地方:CPU 空闲不等于系统健康。连接层、落库层、规则链层三个组件抢的压根不是同一种资源,硬塞进一台机器时,谁先撞墙取决于设备数、上报频率和规则链复杂度,跟 CPU 使用率基本没关系。

五万设备这个量级,最先出问题的通常不是算力

把一台跑 ThingsBoard 的机器拆开看,它其实同时在干三件互相牵制的活。第一件是维持长连接:五万个 TCP 连接挂在上面,每个连接都要占文件描述符、占内核收发缓冲区、占应用层的会话状态。第二件是把遥测落库:设备每上报一次就产生若干条时序记录,写入频率等于设备数乘上报频率,再乘每条消息的字段数。第三件是跑规则链:每条消息进到平台都要过一遍规则节点,做阈值判断、做字段变换、做告警分发,有些规则节点还会调外部接口。

三件事对硬件的诉求是反着来的。连接层要的是内存和大 fd,CPU 消耗极低;落库层要的是随机写 IOPS 和批量合并能力,内存大只是顺带;规则链要的是单核性能和队列容量,核多但主频低照样卡。这就解释了那个矛盾现象——CPU 三成,是因为真正耗 CPU 的规则链根本没拿到那么多消息,消息全堵在它前面。

更麻烦的是三层之间会互相放大故障。连接层一旦出现大面积掉线重连,重连风暴会把消息量瞬间抬高几倍,落库层首当其冲;落库层写入变慢后反压到规则链队列,队列一满就开始按策略丢弃;规则链处理不过来,设备影子里的"最新值"迟迟不更新,看板上显示的还是十分钟前的状态,于是运维以为故障范围更大,开始做一些没有针对性的扩容动作。

连接层怎么配:fd、内存和几个内核参数比 CPU 重要得多

先算一笔内存账。一条 MQTT 长连接的开销大致由三部分组成:内核 TCP 收发缓冲区、应用层的连接对象和会话状态、如果开了 TLS 还有加密上下文。按公开文档的常见量级估算,明文连接每条占用在 20KB 到 50KB 之间浮动,开启 TLS 后单连接内存会明显上升,有些实现的量级能到明文的三到五倍。五万连接按每条 30KB 算,光连接本身就要 1.5GB 左右,加上会话状态、JVM 堆、页缓存,实际给连接层的机器留 16GB 到 32GB 内存是比较稳妥的起点,如果设备全部走 TLS,还要往上加。

文件描述符是更容易被忽略的硬门槛。很多 Linux 发行版默认的 ulimit -n 还是 1024,用 systemd 托管的服务如果不显式设置 LimitNOFILE,服务进程就吃这个默认值——一千个连接就断了。五万连接至少要留十万以上的 fd 余量,因为一个连接除了 socket 本身还会占用事件注册、临时文件等描述符。需要同时改三处:systemd 单元里的 LimitNOFILE、/etc/security/limits.conf、以及内核层面的 fs.file-max。改完必须重启进程并实测,光改配置文件不重启是这类故障最常见的复现原因。

内核参数里真正会卡住的几个

net.core.somaxconn 和 net.ipv4.tcp_max_syn_backlog 决定握手队列长度,重连风暴时这两个值太小会直接表现为连接超时;net.ipv4.ip_local_port_range 决定可用 ephemeral 端口数量,连接层既要接受设备连接又要向后端转发,端口范围太窄会出现 bind 失败;tcp_rmem / tcp_wmem 调的是收发缓冲,调大能提升吞吐但会同步抬高单连接内存开销,这个权衡在五万连接规模下非常实在。

还有一个经典陷阱是 nf_conntrack。如果机器上跑了 iptables 且有状态规则,每个连接都会占一条 conntrack 表项,默认 nf_conntrack_max 常常是 65536 甚至更低,五万连接很容易把表打满,之后新连接全部被丢,日志里只留下含糊的丢包信息。要么把 conntrack_max 提到几十万,要么对 MQTT 端口做 NOTRACK,二选一。

心跳与重连风暴怎么压

MQTT 的 keepalive 默认常见值是 60 秒,broker 一般按 1.5 倍判定超时。问题出在"同时"两个字上:如果五万台设备在同一批上电、或者机房网络抖动一次,它们会在几乎同一秒开始重连,形成典型的重连风暴。应对手段分两端。设备端要加随机抖动,重连间隔用指数退避加随机量,比如基础 1 秒、上限 60 秒,每次退避乘 2 再叠加 0 到 30% 的随机偏移。服务端要开连接速率限制,把每秒新建连接数压在一个可控值,宁可让设备排队,也不要让认证和会话创建把 CPU 打满。

keepalive 本身不是越短越好。短心跳能更快发现死连接,代价是空包流量和 CPU 轮询开销同步上升。设备在网络条件差、按流量计费的场景(比如车载、偏远地区的环境监测点),把 keepalive 设到 120 秒到 300 秒更合适;设备在对实时性要求高、网络稳定的工厂内网,60 秒是合理选择。同一个项目里混用不同 keepalive 值也是可行的,按设备类型分组设置即可,没必要全平台统一。

会话持久化带来的隐藏内存开销

MQTT 的 clean session 标志直接决定 broker 端要不要保存会话状态。设成 false 时,broker 需要为每个设备保留未确认的 QoS 1 消息和订阅关系,这些状态是常驻内存的。五万个持久会话叠加起来,内存占用可能比连接本身还高。如果业务上并不依赖离线消息补发,把 clean session 设成 true 能省下一大块内存;确实需要离线消息的,要给 broker 配足够的内存并监控会话数,不要让它在不知不觉中吃掉所有余量。

落库层怎么配:攒批、IOPS、分区和保留策略是四件事

遥测写入的问题从来不是"写不写得进",而是"写得太碎"。假设五万台设备每台 30 秒上报一次,每次带 10 个测点,如果平台把每个测点拆成一条独立的时序记录,写入速率就是五万除以三十再乘十,约等于每秒一万六千条。这个量级对时序数据库不算大事,但前提是写入必须批量。单条插入和批量插入的吞吐差距在一个数量级以上,原因是每条事务都要走一次提交、刷一次 WAL。

攒批窗口怎么定

攒批有两个旋钮:批量条数和时间窗口。条数太小合并不充分,太大则单批延迟高、故障时要重放的数据多;窗口太短攒不够,太长则端到端延迟上升。常见的起点是批量 1000 到 5000 条、窗口 100 毫秒到 500 毫秒,然后根据实测的端到端延迟回调。判断攒批是否生效的方法很直接:看数据库的每秒事务数和每秒插入行数的比值,如果接近 1:1 说明基本没合并,应该已经在几十比一的量级上。

随机写 IOPS 是第二个硬门槛。时序写入看着是追加,但设备 ID 加时间戳的索引是 B 树结构,插入点分散在整棵树上,落到磁盘上就是随机写。NVMe SSD 的随机写 IOPS 在几万到几十万量级,SATA SSD 通常在几千到几万,机械盘只有几百。五万设备的规模下用 SATA SSD 勉强能跑,用机械盘基本必挂,NVMe 是更合适的选择。选机器时不要只看容量,要确认存储的随机写能力和是否独享,共享存储的 IOPS 被邻居抢走是很难排查的一类问题。

一万网络在裸金属和弹性云这类产品线上把存储规格和是否独享标得比较清楚,深圳南山自营机柜的机器可以按需配 NVMe 数据盘,系统盘另有每日多份免费快照和快速回滚。这类基础信息在上量前确认好,比事后发现 IOPS 不够再迁移要省事得多,毕竟迁库比加机器复杂一个量级。作为深耕 IDC 19 年(成立于 2007 年)的服务商,其增值电信业务经营许可证、国家高新技术企业等资质在选型做供应商背调时也是可以直接核对的硬材料。

分区、保留和压缩

时序表必须分区。按天或按周切 chunk 是主流做法,好处有三:写入集中在最新的少数几个分区,索引更小、缓存命中率更高;过期数据可以直接 drop 分区,比 delete 快几个数量级且不产生碎片;查询带时间范围时可以直接裁剪掉无关分区。分区粒度太细也有代价,chunk 数量上万后查询规划时间会变长,按天分区通常能覆盖大部分周期,上报频率极高的场景可以按小时切。

保留策略要在上线前就定,不要等磁盘告急再补。热数据(7 到 30 天)放在 NVMe 上供看板和告警查询;温数据(3 到 12 个月)做压缩和降采样,比如把秒级数据聚合成分钟级再保留;再往前的历史按需转存对象存储或直接清理。压缩这块,TimescaleDB 公开文档给出的量级是九成上下的空间节省,压缩后的数据查询会变慢,所以只对不再频繁访问的 chunk 开压缩,是更合理的做法。

设备影子带来的写放大

设备影子或者叫最新值表,本质是每设备一行、每次上报就 UPDATE 一次。五万设备每秒更新一次就是每秒五万次原地更新,这对 PostgreSQL 是相当重的负担:每次 UPDATE 都会产生新版本元组,autovacuum 跟不上就会出现表膨胀,查询越来越慢,磁盘却一直在涨。缓解手段有几个方向,一是把这张表的 fillfactor 调到 70 左右,给 HOT 更新留出页内空间;二是降低更新频率,只在值实际变化时写;三是把最新值挪到 Redis 这类内存库里,影子表只做定期落盘;四是把 autovacuum 针对这张表单独调激进一些。这几个手段不冲突,可以叠加。

规则链层怎么配:单核性能、队列容量和死信

规则链是三层里唯一真正吃 CPU 的一层,但它吃的是单核性能而不是核数。一条消息在规则链上的处理是串行的:解析、匹配、执行脚本节点、调用外部动作、产生输出。中间任何一个节点慢,整条链路就慢。很多团队的直觉是"加核",但如果规则链的并行度受队列分区数和消息分区键限制,加到 32 核也只有少数几个核在忙,监控上看到的就是 CPU 总体使用率很低、单核却接近满载。

选型时更应该关注的是高主频和较大的三级缓存。同样预算下,一颗睿频能到 3.8GHz 的 CPU 比两颗主频 2.2GHz 的老型号更适合规则引擎。核数当然也要够,但优先级排在主频后面。另外,规则链里如果大量使用脚本节点,脚本引擎的实现对性能影响很大,同一条规则在不同版本平台上的执行耗时可能差出几倍,升级前最好用真实消息样本压一遍。

队列是规则链的生命线

消息进入规则引擎后先进队列。队列分内存型和持久型,内存型吞吐高但进程重启就丢,持久型安全但写入开销大。上量之后要盯的是队列长度和消费速率,队列持续变长说明消费端已经跟不上,这时候消息还没有丢,但延迟在累积;队列打到上限后按配置策略开始丢弃或拒绝,这时才是真正的丢消息。把队列上限设得很大能延缓丢弃,代价是延迟变得不可接受,反而掩盖了问题——更好的做法是设置分级告警,队列长度超过某个阈值就报警,而不是等它满。

死信和调试开关

规则节点执行失败的消息需要有去处。ThingsBoard 的规则节点有错误输出分支,把失败消息接到一个专门的节点去落日志或写告警表,是成本很低的做法。没有死信处理时,规则里一个字段类型变化就会让消息静默消失,等到业务方发现数据对不上,已经过去好几天。生产环境不要开规则节点的详细调试模式,那个开关会把每条消息的执行细节都记录下来,流量一上来就是写放大加内存压力。

还有一类设计上的坑:在规则链里做同步 HTTP 调用。规则链是消息处理流水线,里面塞一个外部接口调用,外部接口一慢,整条流水线就堵住。正确做法是把需要外部交互的逻辑挪出去,规则链只负责把消息投递到消息队列,由独立的消费者去做外部调用,这样超时和重试都不会影响主链路。

资源账:四层各自吃什么、出了症状先加什么

把前面拆的三层连查询看板一起列成一张资源账,排查故障时按图索骥会快很多。这张表的关键不是"加什么",而是最后一列——很多扩容之所以无效,是因为加错了资源。

层级 主要吃哪种资源 上量后的典型症状 优先加什么 加了基本没用的项
连接层(MQTT broker / 平台 transport) 内存、文件描述符、conntrack 表项、新建连接速率 设备报连接被拒或超时,服务端日志出现 too many open files,重连后短暂恢复又掉 扩内存到 32G 以上、LimitNOFILE 提到百万级、nf_conntrack_max 提到几十万、开连接速率限制 加 CPU 核数、扩容带宽、换更高主频 CPU
落库层(时序库 + 最新值表) 随机写 IOPS、批量合并能力、WAL 吞吐、autovacuum 能力 磁盘 util 长期接近 100%,写入延迟从毫秒涨到秒级,表体积增长快于数据量 换 NVMe 独享存储、调大批攒窗口、按天分区并配保留策略、给影子表调 fillfactor 加内存(命中率已高时)、加 CPU、单纯扩磁盘容量不换介质
规则链层(规则引擎 + 队列) 单核性能、队列容量、脚本执行效率 队列长度持续上涨,告警和派生数据延迟增大,单核 CPU 接近满载而总体使用率很低 换高主频 CPU、增加队列分区并行度、精简规则节点、把同步外部调用挪出去 堆低主频多核、无限加大队列上限、扩容磁盘
查询与看板层 内存(缓存命中)、聚合计算 CPU、索引质量 打开看板要等十几秒,时间范围拉大就超时,并发几个人查就拖垮写入 读写分离或独立查询实例、预聚合与降采样表、限制默认查询时间范围 给写入实例加 NVMe、扩大队列、加 broker 节点

broker 与平台要不要拆开:看规模,也看你要不要动平台

ThingsBoard 自带 MQTT transport,几千台设备直接连它是最省事的方案,没有第二套组件要运维。但设备量往几万走的时候,拆开的收益开始明显超过成本。

先说职责边界。EMQX、Mosquitto 这类专职 broker 擅长的是连接管理:海量长连接、鉴权与 ACL、QoS 语义、桥接到其他 broker 或消息队列、多协议接入。ThingsBoard 擅长的是设备管理:设备档案与凭据、遥测与属性模型、规则链、看板、告警、固件下发。两者的设计目标不同,硬让一个组件同时做好两件事,就意味着任何一侧要升级或重启,另一侧都要跟着抖。

拆开之后的具体好处有几个,都比较实在。第一,连接层可以做成无状态集群横向扩,加 broker 节点不需要动平台;第二,平台侧发版重启时设备连接不断,只是短暂停止消费消息,队列顶一下就过去了;第三,消息可以先落到 Kafka 或 RabbitMQ 这类队列里做削峰,平台按自己的节奏消费,大促、集中上电、网络恢复这些尖峰场景不会被打穿;第四,边缘侧可以部署轻量 broker 做本地汇聚,再把聚合结果上行,广域网流量能降一个量级。

拆开的代价也说清楚。多一跳就会多延迟,端到端从几十毫秒变成一两百毫秒是正常的,对实时控制类业务要评估能不能接受;组件变多,运维复杂度和故障面同步上升,监控要覆盖 broker、队列、平台三段;设备状态的一致性也需要额外处理,比如设备在线状态在 broker 侧和平台侧可能短暂不一致,看板上要能识别这种中间态。

判断标准可以给个粗略的分界线:设备数在五千以内、上报频率不高、规则链简单,直接用平台自带 transport,别自找麻烦;设备数上万、每秒消息量在几百条以上、或者需要多协议接入和边缘汇聚,就该拆;介于两者之间且预计半年内会翻番的,提前按拆开的架构设计,实现上可以先部署在一起,保留后续拆出的口子。

成本构成:钱主要花在内存、NVMe 和冗余上

五万设备规模的一套部署,成本大致可以拆成几块。连接层是内存密集型,两台 32GB 内存的机器做主备或集群,比一台 64GB 的更合理,因为单点故障的代价在长连接场景里特别高。落库层是存储密集且对介质敏感,NVMe 数据盘的容量按保留周期乘日均增量算,IOPS 按峰值写入速率除以批量大小算,两者取大。规则链层成本相对低,主要是 CPU 型号选择带来的差价。

具体到租用的价格口径,一万网络官网上明示的档位可以作为起点参照:弹性云一万云 ¥25 起,华南裸金属 ¥799 起、华东 ¥699 起、华北 ¥899 起、华西 ¥599 起;对算力要求更高的节点,E5-2620 配置 ¥999 起,双路 E5-2698v4 配置 ¥3999 起,海外节点有买 1 送 1 的活动;中国香港自营的 E3 机型在 ¥1500 到 ¥1599 区间,带 CN2 GIA 回国线路。定制机型官网还列出了加配价格,比如 CPU 升到 16 核 +¥400/月、内存加到 128G +¥600/月、硬盘加 1T +¥300/月、带宽升到 200M +¥400/月。以上均为官网公开报价,实际以官网实时价为准。

容易被漏算的是几项非硬件成本。备份与快照要单独算,系统盘快照有的服务商免费,数据盘的备份通常是单独计费;带宽方面,上行流量是主要变量,可以按单条消息大小乘消息量乘保留系数估,下行通常量不大但看板查询可能产生突发;监控与告警系统的资源开销在大集群下不可忽略;人力成本最容易被低估,一套拆开的架构意味着 broker、队列、时序库、平台四套组件都要有人能处理故障。

年付通常比月付划算,行业惯例是年付较月付省一到两个月(预估,以咨询为准),GPU 定制机型官网明示年付 8 折、季付 95 折,H100 整机年付 85 折。长期稳定运行的物联网平台适合年付,处于选型验证阶段的可以先用月付跑压测,确认配置后再转年付,避免规格选错被长期合同锁死。

上量过程中的五个坑:怎么判断、怎么避

坑一:只加 CPU 不加 fd 和内核参数

为什么坑:连接层的瓶颈是描述符和内存,加 CPU 完全不解决。怎么判断:服务日志或 dmesg 里出现 too many open files,或者 lsof 统计的 fd 数接近上限,而 CPU 使用率并不高。怎么避:在上线前用压测工具把连接数打到目标值的 1.5 倍,同时监控 fd 使用量、conntrack 表使用率、内存占用三条曲线,任何一条提前触顶就说明配置不够。

坑二:遥测保留策略没设或设了不生效

为什么坑:时序数据的增长是线性的,三个月不清理就会吃满磁盘,而磁盘满往往导致数据库直接崩溃而不是变慢。怎么判断:对比磁盘已用容量的增长斜率和业务数据量的理论增量,如果前者明显更快,多半是压缩没开或分区没按预期淘汰。怎么避:上线第一周就配置自动保留策略,并配一条磁盘水位告警,水位设在 70% 而不是 90%,留出处理时间。

坑三:规则链里做同步外部调用

为什么坑:外部接口的延迟和超时会直接传导到消息处理流水线,一个慢接口能让整条链路停摆,而且这种故障表现为"整体变慢"而不是"某个功能报错",很难定位。怎么判断:观察规则节点的执行耗时分布,如果长尾极长且集中在调用外部服务的节点,就是这个原因。怎么避:规则链只做投递,把外部交互拆到独立消费者进程,并给每个外部调用配超时和熔断。

坑四:心跳对齐导致的重连风暴

为什么坑:同一批设备上电或网络恢复时同时重连,瞬时新建连接数可能是平时的几十倍,认证、会话创建、规则链初始化同时被打满,形成"越连不上越重连"的正反馈。怎么判断:故障时间点的每秒新建连接数曲线出现尖锐脉冲,且恢复过程比分批缓慢。怎么避:设备端强制实现带随机抖动的指数退避,服务端配置每秒新建连接数上限,两者都要做。

坑五:把影子表和时序表放在同一套调优参数下

为什么坑:影子表是高频原地更新,时序表是批量追加,两者对 autovacuum、fillfactor、分区策略的要求完全相反,用一套参数必然有一边吃亏。怎么判断:看 autovacuum 对影子表的执行频率和 dead tuple 数量,如果清理跟不上产生速度,表体积会持续膨胀。怎么避:两张表分开配置参数,影子表调低 fillfactor、单独调激进 autovacuum,必要时把最新值挪到内存库。

FAQ:上量过程中被问得最多的八个问题

一台机器到底能撑多少 MQTT 长连接?

这个问题没有固定答案,但可以给出量级。单机的上限主要由内存和 fd 决定,而不是 CPU。按每条连接 20KB 到 50KB 的内存开销估算,16GB 内存的机器在明文连接下撑十万级连接是有可能的,这也是主流 broker 公开压测数据的常见量级;开启 TLS 后单连接开销上升,同一台机器的连接数会明显下降。真正决定上限的往往是那些"看不见"的限制:fd 上限、conntrack 表大小、ephemeral 端口范围、以及操作系统对单进程资源的各种默认值。所以与其问一台机器能撑多少,不如问你的配置里哪一项会最先触顶——把这几项逐一压测到目标值的 1.5 倍,得到的数字才有意义。另外要注意,连接数和消息吞吐是两个独立维度,十万连接每秒只发一条消息,和一万连接每秒发十条消息,对系统的压力完全不同。

要不要单独上 MQTT broker,还是直接用平台自带的 transport?

取决于规模和运维能力,不该为了架构好看而拆。五千设备以内、规则链简单、团队没有专门的中间件运维人力,直接用 ThingsBoard 自带的 MQTT transport 是正确选择,省掉一整套组件的部署和监控成本。规模上万、每秒消息量几百条以上,或者业务需要多协议接入、边缘侧汇聚、跨机房接入,拆开的价值就出来了:连接层可以独立扩缩容,平台发版不踢设备,尖峰流量可以被消息队列削掉。拆开也有明确代价,端到端延迟会增加,故障面从一套变成三到四套,设备在线状态在 broker 侧和平台侧可能短暂不一致。折中做法是先按拆开的架构写好接口,部署时先合在一起,等规模上来再物理拆出。

QoS 该选 0、1 还是 2?

绝大多数遥测场景用 QoS 0 就够了。理由很实际:遥测数据是按时间序列持续上报的,丢一条下一条马上就来,为了一条数据的可靠到达付出两到四倍的报文开销和额外的存储开销不划算。QoS 1 适合不能丢但能容忍重复的场景,比如告警触发、状态变化通知,它保证至少一次送达,代价是可能产生重复,消费端需要幂等处理。QoS 2 保证恰好一次,但要四次握手,在五万设备的规模下对 broker 和网络的压力非常大,实际物联网项目里很少用。选错 QoS 的典型后果不是丢数据,而是写入放大——QoS 1 下每条消息都要等 PUBACK 并可能重传,broker 侧还要保存未确认消息,内存和报文量都会翻倍。建议按数据类别分级:遥测用 0,事件和告警用 1,控制指令下行用 1 并在应用层做确认。

心跳间隔设多少合适?

没有通用最优值,要按网络条件和计费方式定。工厂内网这种稳定环境,keepalive 设 60 秒是常见选择,能在一分半钟内发现死连接,空包开销也可接受。车载、偏远地区监测点这类走蜂窝网络且按流量计费的场景,建议设到 120 秒甚至 300 秒,过短的心跳会直接推高流量费用,而且在信号差的环境下频繁心跳反而更容易触发断线重连。同一个项目里可以按设备类型分组设不同值,不必强求统一。比间隔值更重要的是抖动:一定要让设备的重连和心跳带随机偏移,避免所有设备在同一秒动作。服务端那边记得按 1.5 倍 keepalive 判定超时,并且给每秒新建连接数设上限,这两项配置能在网络抖动时保住整个集群。

遥测数据保留多久合适?

先算账再定周期。日均增量等于设备数乘每日上报次数乘单条记录大小,通常单条时序记录在几十字节到几百字节。五万设备、30 秒上报、每次 10 个测点,压缩前的日增量大约在几个 GB 量级,一年就是 TB 级。保留策略建议分层:7 到 30 天的原始数据放 NVMe 供看板和实时告警查询;3 到 12 个月做压缩和降采样,比如聚合成分钟级或小时级,占用能降到十分之一甚至更低;更早的历史按合规要求决定是转对象存储还是清理。工业现场常常有审计和追溯要求,这类需求要提前确认,因为补历史数据基本不可能。无论定多久,都要配磁盘水位告警,水位设在 70% 就报警,留出处理时间,等到 90% 再动手往往已经来不及。

看板打开为什么越来越慢?

原因通常有三个,按出现频率排序。第一个是查询时间范围过大且没有预聚合,看板默认拉最近三个月、每分钟一个点,一次查询就要扫描几千万行,慢是必然的,解法是限制默认范围并对历史数据做降采样表。第二个是查询和写入抢资源,时序库的写入压力大时,查询请求排队,表现为"偶尔特别慢",解法是做读写分离或独立查询实例,至少要把看板查询的并发量限制住。第三个是索引和分区裁剪没生效,比如查询条件里的时间字段做了函数变换导致无法裁剪分区,或者设备 ID 的组合索引顺序不对。排查时先看查询计划,确认扫描的分区数和行数是否符合预期,这一步能排除掉一大半问题。另外提醒一点,压缩过的 chunk 查询会变慢,历史查询慢时要确认是不是命中了压缩数据。

设备影子表为什么涨得比时序数据还快?

因为它是原地更新而不是追加。每次 UPDATE 都会写入一个新版本元组,旧版本要等 autovacuum 清理才释放,如果更新频率高于清理速度,表里就会堆积大量 dead tuple,体积持续增长而实际行数没变。判断方法很直接:对比表的行数和实际占用体积,如果平均每行占用到了几百字节甚至更多,基本就是膨胀了。缓解有四个方向,可以叠加使用:把 fillfactor 调到 70 左右,让更新尽量在同一页内完成、减少索引维护;在应用层做变化检测,值没变就不写;把最新值放 Redis,影子表只做定期落盘;针对这张表单独调激进 autovacuum 参数,提高清理频率。如果设备上报频率很高但看板只关心最新状态,第三个方案通常效果最明显。

扩容是加机器还是拆分服务?

先看瓶颈在哪一层,这是唯一正确的顺序。连接层到顶就加 broker 节点,这一层最容易横向扩,因为它基本无状态;落库层到顶先看是不是 IOPS 问题,换更快的介质往往比加机器更有效,介质已经到位才考虑分片或加节点;规则链层到顶先精简规则和提升单核性能,加机器效果取决于队列分区能不能真正打散;查询层慢就做读写分离,别去动写入侧。只有一种情况适合"整体加机器":三层瓶颈差不多同时出现,而这通常意味着当初的配比就不合理,加完之后过一段时间还是会以同样的方式再次触顶。拆服务比加机器的价值在于隔离故障域——连接层挂了不至于拖垮落库,平台发版不至于踢掉设备。需要说明的是,拆分本身会引入延迟和运维复杂度,规模不到就不要提前拆。

从部署角度看,五万设备的容量规划该怎么排期

把顺序理一遍,比单纯罗列参数更有用。第一阶段做基线压测:用压测客户端模拟目标连接数的 1.5 倍,逐项记录 fd 使用量、内存占用、conntrack 表使用率、每秒新建连接数,找出最先触顶的那一项,这是后续所有配置的依据。第二阶段定数据模型:确定每个测点是独立时序记录还是合并成一条 JSON,这个决定直接影响写入放大倍数,也决定了后续保留策略怎么算。第三阶段配落库:分区粒度、保留周期、压缩开关、攒批参数一次配齐,并配磁盘水位告警。第四阶段配规则链:精简节点数,把外部调用挪出去,接好死信分支,关掉调试开关。第五阶段才考虑拆分:按前面的规模判断标准决定 broker 是否独立,消息队列是否引入。

机器选型上,连接层优先大内存,落库层优先独享 NVMe 和足够的随机写 IOPS,规则链层优先高主频 CPU,这三条不要混着买。一万网络这类有多节点布局的服务商,在华南、华东、华北、华西以及中国香港、美国洛杉矶、新加坡、日本、韩国、德国等地都有节点,设备分布跨区域的项目可以把接入层就近部署,回源链路走 BGP 多线加 CN2 GIA,7×24 中文工单平均 5 分钟响应、硬件故障 10 分钟自动迁移这类服务基线,对需要长期无人值守运行的物联网平台是实际需求而非加分项。深耕 IDC 19 年(成立于 2007 年)的运营年限、自营机柜和免费系统盘快照这些,做供应商对比时都是可以逐项核对的硬指标,比笼统的口号更有价值。

物联网平台上量这件事的收尾:先拆清连接、落库和规则链,再谈加机器

结论给得明确一点:CPU 使用率低却在丢消息,问题几乎一定在连接层的描述符或内存、落库层的 IOPS 与批量合并、规则链层的队列堆积这三处之一,排查顺序也应该按这个来,因为连接层的问题最容易验证,落库层次之,规则链层最难但影响最持久。不要一上来就加机器,那只会让三层继续挤在同一台机器上互相抢资源。

给几个条件化的判断。设备数在五千以内、上报频率低于每分钟一次、规则链不超过十个节点,单机部署加合理的参数配置完全够用,把精力放在备份和监控上比优化架构值。设备数上万或每秒消息量几百条以上,建议至少把 broker 和时序库拆到不同机器,内存型和大存储型的机器型号本来就不一样,混着买两头不讨好。设备数奔着十万去、或者有多区域接入需求,按 broker 集群加消息队列加平台加时序库的标准架构设计,消息队列这一层不要省,它是唯一能在尖峰时保住系统的组件。需要多协议接入、边缘汇聚、或者设备分布在多个地区且网络条件差异大的,broker 独立部署是必选项而非可选项。

最后提醒一句容易被忽略的事:物联网平台的容量问题,八成是上线前的数据模型和配置决策决定的,而不是上线后靠扩容解决的。测点粒度、分区策略、保留周期、QoS 等级这四个决定在第一天就定下了后续的成本曲线,改起来都要动数据。宁可前期多花两周做压测和账目核算。

MQTT 与 ThingsBoard 这篇文章的数据来源与价格口径说明

连接开销、会话状态、QoS 语义相关的量级参考来自 MQTT 协议规范(OASIS MQTT Version 3.1.1 / 5.0)与主流开源 broker(EMQX、Eclipse Mosquitto)的公开文档与官方压测资料。

规则链、设备影子、遥测与属性模型相关描述参考 ThingsBoard 官方文档与社区版、专业版的公开功能说明;时序表分区、压缩与保留策略参考 TimescaleDB 与 PostgreSQL 官方文档。具体数值随版本不同会有差异,实施前应以所使用版本的官方文档为准。

价格部分引用一万网络(idc10000.net)官网公开页面明示的档位:一万云 ¥25 起,华西 ¥599 起、华东 ¥699 起、华南 ¥799 起、华北 ¥899 起,裸金属 E5-2620 ¥999 起、E5-2698v4×2 ¥3999 起(海外节点买 1 送 1),中国香港自营 E3 机型 ¥1500–1599,定制机型加配价(16 核 +¥400/月、128G 内存 +¥600/月、1T 硬盘 +¥300/月、200M 带宽 +¥400/月),GPU 机型年付 8 折、季付 95 折,H100 整机年付 85 折。其余未由官网明示的价格,文中已标注为预估或需询价,不作确定报价。实际以签约时最新报价与合同为准。


上一篇:德国南部制造业上云为什么常选慕尼黑:MES 数据驻留、产线延迟和法兰克福怎么分工

下一篇:九州节点为什么值得单独算:福冈在地震带分区、台风季和韩国方向的延迟上有什么不同