ThingLinks 平台性能分析与容量评估报告
1. 报告说明
本报告面向 ThingLinks 单节点部署,分析在 Linux 服务器、数据库独立部署条件下的平台消息接入、协议解析、告警判断、规则执行和日志入库能力。
报告中的容量数字是根据平台当前实现、批量入库模型、线程配置和工程经验给出的建议容量区间,用于制定压测目标和生产选型,不代表已经在目标服务器上完成的正式实测结果。正式上线前应使用本文测试模型,在实际服务器、网络和数据结构下执行不少于 60 分钟的稳定性压测,并用实测数据替换建议值。
平台性能需要同时观察两个不同结果:
- 实时处理能力:消息是否成功接收、解析、更新实时状态并完成规则判断。
- 持久化能力:设备日志、告警记录、联动告警和指令记录是否完整写入数据库。
平台日志采用有界内存队列异步批量写入。数据库写入速度低于消息进入速度时,实时数据和规则判断仍可能正常,但队列会持续积压;队列满后,新到的日志记录会被丢弃。因此不能只观察接口是否正常,还必须检查队列积压和日志完整率。
2. 测试环境假设
2.1 服务器拓扑
| 节点 | 建议配置 | 说明 |
|---|---|---|
| 应用服务器 | 8 核 CPU、16 GB 内存、Linux 64 位、JDK 17 | 部署 ThingLinks、网络组件和 Redis;不与数据库共用 CPU、内存和磁盘 |
| 数据库服务器 | 8 核 CPU、16 GB 内存、NVMe SSD、Linux 64 位 | 与应用服务器独立部署,内网延迟建议小于 1 ms |
| 压测服务器 | 8 核 CPU、16 GB 内存或更高 | 单独部署压测程序,避免压测客户端占用应用服务器资源 |
| 网络 | 至少 1 Gbps 内网 | 应用与数据库之间不经过公网、NAT 或限速代理 |
为保证两种存储方案可比,数据库节点统一按 8 核 16 GB、NVMe SSD 估算:
- MySQL 方案:业务数据和设备日志都存储在 MySQL 8.0。
- TDengine 方案:MySQL 保存设备、产品、规则等业务数据,设备日志切换到 TDengine 3.x。对比测试时可以将 MySQL 与 TDengine 部署在同一台独立数据库服务器;生产环境数据量较大时,建议将 TDengine 再拆分为独立节点,避免两种数据库争抢磁盘和内存。
2.2 软件与系统建议
| 项目 | 建议值 |
|---|---|
| 操作系统 | Rocky Linux、AlmaLinux、Ubuntu Server 或同级发行版 |
| JDK | JDK 17,G1 GC |
| JVM 堆内存 | -Xms4g -Xmx8g,其余内存留给直接内存、线程栈和系统页缓存 |
| 文件句柄 | ulimit -n 不低于 200000 |
| MySQL | MySQL 8.0,InnoDB Buffer Pool 建议 8 至 10 GB |
| TDengine | TDengine 3.x,日志保留期按业务量设置 |
| Redis | 建议启用持久化监控,不与压测客户端共用实例 |
| 时间同步 | 应用、数据库和压测机统一使用 NTP |
Linux 长连接测试前建议检查以下内核参数:
fs.file-max = 1000000
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_fin_timeout = 30
参数需要结合企业安全规范调整。不要在不了解现网影响的情况下直接复制到生产服务器。
3. 平台性能模型
3.1 当前批处理架构
平台对以下数据支持异步批量入库:
| 数据类型 | 默认批次大小 | 默认队列容量 | 默认 worker 数 |
|---|---|---|---|
| 设备日志 | 500 | 10000 | 8 |
| 指令下发记录 | 200 | 5000 | 1 |
| 设备告警记录 | 200 | 5000 | 4 |
| 联动告警记录 | 100 | 2000 | 2 |
设备日志、告警和联动告警会按设备或规则进行哈希分片,同一设备的数据保持顺序,不同设备由多个 worker 并行写入。
队列容量是短时缓冲,不是可靠消息存储。以设备日志队列 10000 条为例:
- 当数据库比入口吞吐少处理 1000 条/秒时,理论上约 10 秒就会填满。
- 队列满后平台会丢弃最新进入的日志,避免写库阻塞拖垮实时消息链路。
- 修改队列容量会重建处理器,当前尚未入库的数据可能被丢弃,压测期间不要频繁修改。
3.2 设备数不等于消息吞吐
设备在线数量和每秒消息数必须分开描述。消息吞吐计算公式为:
每秒消息数 = 在线设备数 / 单设备上报周期(秒)
| 在线设备数 | 上报周期 | 平均消息数/秒 | 每日消息量 |
|---|---|---|---|
| 1000 | 60 秒 | 17 | 144 万 |
| 10000 | 60 秒 | 167 | 1440 万 |
| 10000 | 10 秒 | 1000 | 8640 万 |
| 50000 | 30 秒 | 1667 | 1.44 亿 |
| 50000 | 5 秒 | 10000 | 8.64 亿 |
即使平台能实时处理 10000 条/秒,全量保留一年也会产生超过 3000 亿条记录。高频场景必须同时设计采样、聚合和保留期,不能只依靠扩容数据库。
4. 协议选择与测试基线
4.1 推荐基线协议
性能基线建议采用平台内置 MQTT Broker:
- MQTT 适合设备长连接、持续上报和服务端下行控制。
- 基线使用 QoS 0,避免确认包影响纯消息处理能力。
- 消息体使用约 512 B 的 JSON,包含设备 SN、时间和 5 至 10 个属性。
- 每台设备使用独立 Client ID,保持长连接,不在每次上报时重新连接。
- 压测消息应尽量贴近真实协议解析逻辑,不能只发送空字符串或固定心跳包。
4.2 协议对性能的影响
| 协议/模式 | 性能特点 | 建议用途 |
|---|---|---|
| MQTT QoS 0 | 长连接、协议开销较低,没有消息确认 | 作为平台最大吞吐基线 |
| MQTT QoS 1 | 至少一次投递,需要 PUBACK,可能出现重复消息 | 作为生产可靠传输场景,吞吐通常低于 QoS 0 |
| MQTT QoS 2 | 往返次数多,CPU 和网络开销高 | 除非业务强制要求,不建议作为高频上报模式 |
| MQTT TLS | 稳态传输影响可控,但批量建连时握手开销明显 | 生产公网接入应单独测试 TLS 建连风暴 |
| TCP Server | 协议头开销小,正确设计粘包拆包时吞吐较高 | 私有协议、高频工业设备 |
| WebSocket | 基于 TCP,存在帧封装和代理层开销 | 浏览器、H5 或只能使用 WebSocket 的设备 |
| HTTP | 单次请求开销大;短连接场景更明显 | 低频上报、Webhook,不建议用于秒级海量设备 |
| UDP | 无连接、吞吐高,但不保证到达和顺序 | 可容忍丢包的遥测;不能只用接收成功率评价可靠性 |
| CoAP | 适合低功耗设备;Confirmable 模式存在重传 | 低频、小报文设备,应单独测试重传和超时 |
经验上,在相同消息体和规则配置下:
- MQTT QoS 1 的吞吐可能比 QoS 0 低约 15% 至 35%。
- TLS 稳态传输可能降低约 10% 至 25%,大量设备同时握手时影响更大。
- WebSocket 通常比直接 TCP/MQTT 多约 10% 至 20% 的处理开销。
- HTTP 短连接的可承载消息数可能比 MQTT 长连接低 40% 以上。
这些比例只用于制定压测档位,最终应以实际协议插件、报文大小、证书算法和网络环境为准。
5. 告警频率与规则配置
告警测试需要同时记录“条件命中率”和“实际告警生成率”。平台告警规则支持节流时间,在该时间内同一告警不会重复触发。
5.1 生产建议
| 告警类型 | 建议节流时间 | 说明 |
|---|---|---|
| 普通状态或阈值告警 | 60 秒 | 防止设备每次上报都生成相同告警 |
| 需要短信、电话、Webhook 的告警 | 300 秒或更长 | 避免通知风暴和第三方接口过载 |
| 高频波动告警 | 300 至 900 秒,并增加恢复条件 | 建议配合迟滞区间,避免阈值附近反复触发 |
| 安全类关键事件 | 按业务要求设置 | 可以缩短,但应评估告警写库和动作下发压力 |
不建议在生产环境将大量规则的节流时间设置为 0。假设入口为 10000 条/秒,30% 消息命中告警且每条都生成记录,将产生 3000 条告警/秒;如果每条告警再下发一条指令,还会额外产生约 3000 次下行和 3000 条指令记录/秒。
5.2 压测告警档位
| 档位 | 条件命中率 | 告警节流 | 动作配置 | 测试目的 |
|---|---|---|---|---|
| A | 0% | 60 秒 | 无 | 测试纯接入、解析和日志入库 |
| B | 1% | 60 秒 | 无或 1 个动作 | 模拟正常生产告警比例 |
| C | 10% | 60 秒 | 每次 1 个设备指令 | 模拟异常集中出现 |
| D | 30% | 0 秒 | 每次 1 个设备指令 | 极端告警和下行压力测试 |
| E | 100% | 0 秒 | 3 个并行动作 | 故障边界测试,不作为生产容量依据 |
如果需要准确制造 10% 或 30% 的实际告警记录,必须关闭节流,或让不同设备、不同规则轮流命中。否则虽然条件持续满足,平台会因为节流而不再生成新告警。
6. 建议容量结论
以下容量基于:应用服务器 8 核 16 GB、数据库服务器 8 核 16 GB、NVMe SSD、1 Gbps 低延迟内网、MQTT QoS 0、约 512 B JSON、批量入库开启、单条消息包含一组普通属性。
“建议持续值”表示生产环境建议控制在该区间内,并预留约 30% 资源处理流量波动、管理端查询、GC 和设备重连。“短时峰值”只适合作为 5 至 10 分钟峰值目标,不能直接作为长期运行能力。
6.1 不保存设备日志
| 场景 | 建议持续吞吐 | 短时峰值目标 | 主要瓶颈 |
|---|---|---|---|
| 无告警、仅解析实时数据 | 15000 至 20000 条/秒 | 25000 条/秒 | 协议解析、缓存更新、事件分发 |
| 1% 告警,不执行下行 | 12000 至 18000 条/秒 | 22000 条/秒 | 规则匹配、少量告警写入 |
| 10% 告警,每次 1 个设备指令 | 10000 至 15000 条/秒 | 18000 条/秒 | 告警生成、下行、指令记录 |
| 30% 告警、关闭节流、每次 1 个指令 | 8000 至 12000 条/秒 | 15000 条/秒 | 告警与指令写库、下行网络 |
关闭设备日志后,应用节点本身可以处理较高消息吞吐,但告警和指令记录仍会写入数据库。高告警比例下,数据库仍可能成为瓶颈。
6.2 日志存储到 MySQL
| 场景 | 建议持续吞吐 | 短时峰值目标 | 说明 |
|---|---|---|---|
| 全量设备日志,无告警 | 4000 至 6000 条/秒 | 8000 条/秒 | 需要开启设备日志批量入库 |
| 全量日志,1% 告警 | 4000 至 6000 条/秒 | 7500 条/秒 | 适合常规中型项目 |
| 全量日志,10% 告警并下发指令 | 3000 至 5000 条/秒 | 6500 条/秒 | 多张表同时高频写入 |
| 全量日志,30% 告警并下发指令 | 1500 至 3000 条/秒 | 4000 条/秒 | 不建议作为长期生产配置 |
MySQL 方案的限制通常不在应用 CPU,而在以下方面:
- 日志表索引维护和页分裂。
- InnoDB redo、binlog 和刷盘延迟。
- 大表查询、分页、删除历史数据与写入争抢 I/O。
- 批处理失败后降级单条重试,进一步放大数据库压力。
MySQL 全量日志长期超过 5000 条/秒时,不建议仅通过增大应用队列掩盖问题。应降低存储频率、缩短保留期、进行表分区,或切换到 TDengine。
6.3 日志存储到 TDengine
| 场景 | 建议持续吞吐 | 短时峰值目标 | 说明 |
|---|---|---|---|
| 全量设备日志,无告警 | 12000 至 18000 条/秒 | 22000 条/秒 | 按设备子表、多表批量写入 |
| 全量日志,1% 告警 | 10000 至 16000 条/秒 | 20000 条/秒 | MySQL 仍承担少量业务写入 |
| 全量日志,10% 告警并下发指令 | 8000 至 12000 条/秒 | 15000 条/秒 | 应同步评估告警是否也切换 TDengine |
| 全量日志,30% 告警并下发指令 | 5000 至 8000 条/秒 | 10000 条/秒 | 瓶颈转向规则、下行和告警处理 |
TDengine 消费器会按设备 SN 分组,将同一批次的多个设备子表拼成多表插入 SQL,适合时序日志。批量写入失败时会降级为单条重试,因此以下情况仍会明显降低性能:
- 单条 JSON 属性过大。
- 设备 SN 或数据中包含异常字符导致批次失败。
- 应用与 TDengine 之间网络抖动。
- 同一数据库服务器上 MySQL 和 TDengine 同时高负载。
对于持续 10000 条/秒以上并要求全量留存的项目,建议 TDengine 使用独立数据库节点,而不是与 MySQL 共用一台 8 核 16 GB 服务器。
6.4 MySQL 与 TDengine 对比
| 对比项 | MySQL 日志 | TDengine 日志 |
|---|---|---|
| 适合场景 | 中低频设备、日志量可控、查询模型简单 | 高频遥测、长时间时序数据、大量设备 |
| 建议持续全量日志吞吐 | 4000 至 6000 条/秒 | 12000 至 18000 条/秒 |
| 大表维护 | 需要分区、索引和定期清理 | 使用超级表、子表和 KEEP 策略 |
| 复杂业务关联查询 | 方便 | 不建议承担复杂事务关联 |
| 写入扩展性 | 较依赖磁盘、索引和事务配置 | 更适合批量时序写入 |
| 故障影响 | 日志写入可能影响业务库 | 日志库与业务库可隔离 |
7. 在线连接容量
在线连接数主要消耗文件句柄、直接内存、连接对象和心跳处理资源,与消息吞吐不是同一个指标。
在 8 核 16 GB Linux 单应用节点上,建议按以下档位设计 MQTT 长连接测试:
| 连接模式 | 建议生产连接数 | 压测目标 | 前提 |
|---|---|---|---|
| MQTT 非 TLS、低频上报 | 20000 | 30000 至 50000 | 文件句柄和内核参数已调整 |
| MQTT TLS、低频上报 | 10000 至 20000 | 30000 | 避免所有设备同时握手 |
| 高频活跃连接 | 由总消息吞吐反推 | 不单独按连接数承诺 | 例如 10000 台设备每秒上报就是 10000 条/秒 |
50000 个连接不等于平台可以同时处理 50000 条/秒。连接保持测试应让设备每 30 至 60 秒上报一次;消息吞吐测试则逐步缩短上报周期。
需要增加重连风暴测试:让 10000 台设备在 5 分钟内分批重连,而不是同一毫秒全部连接。生产设备也应实现随机退避,避免平台或网络恢复后集中重连。
8. 完整压测场景设计
8.1 阶梯吞吐测试
按 1000、2000、5000、8000、10000、15000、20000 条/秒逐级增加,每档运行 15 分钟。出现以下任一情况时停止继续加压:
- 应用 CPU 连续 5 分钟高于 85%。
- 数据库 CPU 或磁盘利用率连续高于 90%。
- 日志队列持续增长且不能回落。
- 出现队列满、日志丢弃或批量写入持续降级。
- 消息处理 P99 延迟超过 1 秒。
- JVM 频繁 Full GC 或堆内存无法回落。
8.2 稳定性测试
选择阶梯测试最大稳定值的 70% 至 80%,连续运行 8 至 24 小时。重点检查:
- 内存是否持续增长。
- 数据库连接池是否泄漏。
- 日志行数与发送消息数差异是否扩大。
- 告警、联动和下行记录是否完整。
- 每小时吞吐和延迟是否出现周期性下降。
- 凌晨数据清理任务是否影响写入。
8.3 峰值与恢复测试
先以建议持续值运行 30 分钟,再将流量提升至 1.5 倍并保持 5 分钟,随后恢复正常流量。要求:
- 峰值期间不发生进程退出或连接大面积断开。
- 队列可以短时增长,但流量恢复后应在 5 分钟内清空。
- 不出现持续性的批量写入失败。
8.4 大报文测试
分别使用 256 B、512 B、1 KB、4 KB 和 16 KB 报文测试。容量表以约 512 B 为基线,报文增大后 JSON 解析、内存复制、数据库字段长度和网络带宽都会增加。
特别是 4 KB 以上报文,不应直接沿用 512 B 场景的吞吐结论。
8.5 规则复杂度测试
至少覆盖以下规则组合:
- 无规则。
- 每台设备 1 条简单阈值规则。
- 每台设备 5 条规则,每条包含 3 个条件。
- 规则编排包含串行动作、并行动作和延时节点。
- 告警后执行 HTTP、MQTT 或设备指令。
规则数量和条件数量会增加每条消息的 CPU 消耗。容量报告必须记录测试时启用的规则数量,不能只记录消息数。
8.6 查询与写入混合测试
压测期间同时模拟管理端用户:
- 10 至 30 个用户查看设备列表和实时状态。
- 查询最近 1 小时、24 小时和 7 天历史数据。
- 查询告警列表并执行分页。
- 导出日志或告警记录。
只测试写入而不测试查询,会高估生产容量,尤其是 MySQL 全量日志方案。
9. 验收指标
9.1 实时链路
| 指标 | 建议验收值 |
|---|---|
| 消息接收成功率 | 不低于 99.99% |
| 协议解析成功率 | 合法报文不低于 99.99% |
| 实时处理 P95 | 小于 200 ms |
| 实时处理 P99 | 小于 500 ms |
| 应用 CPU | 稳态小于 70%,短峰值小于 85% |
| JVM 堆使用率 | 稳态小于 70%,GC 后能够回落 |
| Full GC | 稳态测试期间不应持续发生 |
9.2 持久化链路
| 指标 | 建议验收值 |
|---|---|
| 日志完整率 | 要求完整存储时不低于 99.99% |
| 告警记录完整率 | 不低于 99.99% |
| 队列丢弃 | 正式容量测试必须为 0 |
| 队列积压 | 稳态不持续增长;峰值结束后可恢复到低水位 |
| 数据库 CPU | 稳态小于 70% |
| 数据库磁盘利用率 | 稳态小于 80% |
| 批量写入降级 | 不应连续出现批量失败后单条重试 |
如果业务允许丢弃部分设备历史日志,可以单独降低“设备日志完整率”要求,但必须保证告警、规则执行和实时状态的验收指标不降低。
10. 推荐平台配置
10.1 MySQL 日志方案
| 配置 | 建议值 |
|---|---|
| 设备日志批量入库 | 开启 |
| 设备日志批次 | 500,观察数据库后可调整到 800 至 1000 |
| 设备日志队列 | 20000 至 50000,不建议无限增大 |
| 告警批量入库 | 开启 |
| 告警批次 | 200 至 500 |
| 联动告警批量入库 | 开启 |
| 联动告警批次 | 100 至 200 |
| 设备日志保留期 | 建议 7 至 30 天,按实际数据量确定 |
| 告警节流 | 普通告警 60 秒,通知类告警 300 秒以上 |
如果提高队列后积压仍持续增长,说明数据库处理能力不足,应降低入口速度或调整存储架构,而不是继续增加内存队列。
10.2 TDengine 日志方案
| 配置 | 建议值 |
|---|---|
tdengine.enabled | true |
device-log-enabled | true |
| 设备日志批量入库 | 开启 |
| 设备日志批次 | 500 至 1000 |
| 设备日志 worker | 8 核服务器先使用 8,确认数据库有余量后再测试 12 或 16 |
| TDengine 保留期 | 使用 keep-days 或 TDengine KEEP 策略管理 |
| 告警/指令是否进 TDengine | 根据查询要求单独测试,不建议未经验证一次全部切换 |
worker 不是越多越好。数据库已经达到 CPU、磁盘或连接上限时,增加 worker 只会产生更多并发 SQL 和重试。
11. 风险与扩容建议
11.1 单节点适用范围
8 核 16 GB 单应用节点适合以下典型规模:
- 1 万至 3 万 MQTT 长连接、设备低频上报。
- 5000 至 10000 条/秒的综合生产消息量。
- MySQL 中等规模日志,或 TDengine 高频时序日志。
- 告警比例处于 1% 左右,并配置合理节流。
这不是设备数量上限。设备每 60 秒上报一次时,5 万设备只有约 833 条/秒;设备每秒上报一次时,1 万设备就是 10000 条/秒。
11.2 需要扩容的信号
出现以下情况之一时,应考虑拆分或集群部署:
- 持续消息量超过 15000 至 20000 条/秒。
- MQTT 长连接超过 3 万且同时存在高频上报。
- 告警和规则动作占比超过 10%。
- 需要全量保存 10000 条/秒以上设备日志。
- 管理端历史查询明显影响写入。
- 单机故障不可接受,需要高可用。
扩容优先顺序建议为:
- 数据库与应用分离。
- 设备日志切换 TDengine,并设置合理保留期。
- 将 Redis 独立部署。
- 按网络组件或设备分组拆分接入节点。
- 使用集群版进行多节点水平扩展。
12. 综合结论
- 在 8 核 16 GB Linux 应用服务器、数据库独立部署的条件下,ThingLinks 的实时消息处理能力高于 MySQL 全量日志写入能力。不开启设备日志时,MQTT QoS 0 场景建议按 15000 至 20000 条/秒进行容量规划;包含 30% 极端告警和下行时,建议控制在 8000 至 12000 条/秒。
- MySQL 全量保存设备日志时,建议持续吞吐控制在 4000 至 6000 条/秒。超过该范围后,数据库磁盘、索引和大表维护通常先达到瓶颈。
- TDengine 更适合高频时序日志。在同等 8 核 16 GB 数据库节点条件下,建议全量日志持续吞吐按 12000 至 18000 条/秒评估;高告警比例下应降低到 8000 至 12000 条/秒。
- 告警频率对容量影响很大。生产普通告警建议至少配置 60 秒重复告警节流,需要外部通知或自动下行的告警建议 300 秒以上。30% 命中且关闭节流只能作为极端压测,不应作为正常生产设计。
- MQTT Broker、QoS 0、长连接应作为最大吞吐基线;生产还必须补充 QoS 1、TLS、重连风暴、大报文、复杂规则和查询写入混合测试。
- 平台队列满时会优先保护实时链路并丢弃日志,因此正式报告必须同时给出消息成功率、日志完整率、队列积压、数据库写入速率和告警动作成功率,不能只写 CPU 和内存占用。
最终生产容量应取 8 至 24 小时稳定性测试最大无丢失吞吐的 70% 至 80%,并保留至少 20% 至 30% 的资源余量。