单节点部署与基准测试:Docker Compose部署、使用JMeter/TB内部工具进行压力测试、理解吞吐量(TPS)与延迟指标
好,咱们直接进入正题。这一章我打算带你亲手搭建一个ThingsBoard单节点环境,然后给它来一顿“压力测试”。说白了,就是看看这小家伙到底能吃下多少活儿。
我个人习惯,在调优之前,先拿到一组基准数据。没有基准,你后面做的所有优化都是“盲人摸象”。你想想看,你改了个参数,系统快了还是慢了?没有对比数据,你根本说不清楚。
2.1 用Docker Compose快速部署单节点
部署ThingsBoard,我推荐用Docker Compose。为什么?因为干净、可复现、好清理。我在项目中遇到过好几次,生产环境里因为手动部署漏了某个依赖,排查了一整天。用Compose,一个文件搞定所有。
下面这个是我常用的单节点部署文件,去掉了高可用的部分,专注于性能测试。
version: '3.8'
services:
mypostgres:
image: postgres:15
environment:
POSTGRES_DB: thingsboard
POSTGRES_PASSWORD: postgres
volumes:
- tb-postgres-data:/var/lib/postgresql/data
networks:
- tb-net
mytb:
image: thingsboard/tb:3.6.1
depends_on:
- mypostgres
ports:
- "8080:8080"
- "1883:1883"
- "5683:5683/udp"
environment:
TB_QUEUE_TYPE: in-memory
SPRING_DATASOURCE_URL: jdbc:postgresql://mypostgres:5432/thingsboard
SPRING_DATASOURCE_USERNAME: postgres
SPRING_DATASOURCE_PASSWORD: postgres
volumes:
- tb-data:/data
networks:
- tb-net
volumes:
tb-postgres-data:
tb-data:
networks:
tb-net:
driver: bridge
嗯,这里要注意。我把队列类型设成了 in-memory。这是单节点测试的常用配置,省去了Kafka或RabbitMQ的依赖。但你要记住,生产环境千万别这么干,否则一重启,队列里的消息全丢了。
启动命令很简单:
docker-compose up -d
等个一两分钟,看看日志:
docker-compose logs -f mytb | grep "Started ThingsBoard Server"
看到“Started”字样,就说明部署成功了。这时候访问 http://localhost:8080,用默认账号 sysadmin@thingsboard.org / sysadmin 登录。
2.2 准备测试数据:设备与遥测
基准测试不能空跑。你得先创建一批模拟设备,让它们持续上报数据。我个人习惯用TB自带的REST API来批量创建设备。
下面这个Python脚本,我经常用它来生成测试数据:
import requests
import json
import time
BASE_URL = "http://localhost:8080"
HEADERS = {
"Content-Type": "application/json",
"Accept": "application/json"
}
# 先登录获取token
login_data = {
"username": "tenant@thingsboard.org",
"password": "tenant"
}
login_resp = requests.post(f"{BASE_URL}/api/auth/login", json=login_data, headers=HEADERS)
token = login_resp.json().get("token")
HEADERS["X-Authorization"] = f"Bearer {token}"
# 批量创建100个设备
for i in range(100):
device_data = {
"name": f"benchmark-device-{i:03d}",
"type": "benchmark"
}
resp = requests.post(f"{BASE_URL}/api/device", json=device_data, headers=HEADERS)
if resp.status_code == 200:
print(f"设备 {i:03d} 创建成功")
else:
print(f"设备 {i:03d} 创建失败: {resp.text}")
time.sleep(0.1) # 稍微慢一点,别把API打挂了
跑完这个脚本,你就有了100个测试设备。接下来,我们需要让这些设备上报数据。你可以用JMeter来模拟,也可以用TB自带的REST API直接推送。
2.3 使用JMeter进行压力测试
JMeter是压测的老牌工具了。我一般用它来模拟大量设备并发上报遥测数据。
先创建一个测试计划,结构如下:
- 线程组: 设置并发用户数(比如50个线程)
- HTTP请求默认值: 设置服务器地址和端口
- HTTP头管理器: 添加
Content-Type: application/json和X-Authorization: Bearer {token} - HTTP请求: 模拟设备上报遥测
HTTP请求的配置如下:
方法: POST
路径: /api/v1/{device_token}/telemetry
Body: {"temperature": 25.5, "humidity": 60, "timestamp": 1700000000000}
这里有个坑。每个设备都有自己的访问令牌(device token)。你需要在创建设备后,通过API获取它的token。我曾经因为忘了这茬,压测了半天,结果所有数据都报401错误。
获取设备token的API:
GET /api/device/{device_id}/credentials
返回结果里有个 credentialsId 字段,那就是设备的token。
2.4 使用TB内部工具进行压力测试
除了JMeter,ThingsBoard本身也提供了一些压测工具。我个人觉得,TB自带的 mqtt-benchmark 工具更贴近实际场景,因为它模拟的是真实的MQTT协议通信。
TB的Docker镜像里其实内置了一个压测脚本,位置在 /usr/share/thingsboard/tools/mqtt-benchmark.js。你可以这样调用:
docker exec -it mytb node /usr/share/thingsboard/tools/mqtt-benchmark.js \
--host localhost \
--port 1883 \
--clients 50 \
--rate 10 \
--size 50 \
--duration 60
参数说明:
| 参数 | 说明 | 我的建议值 |
|---|---|---|
| --clients | 模拟的客户端数量 | 50-200 |
| --rate | 每个客户端每秒发送的消息数 | 1-10 |
| --size | 每条消息的payload大小(字节) | 50-200 |
| --duration | 测试持续时间(秒) | 60-300 |
跑完之后,控制台会输出类似这样的结果:
Total messages sent: 30000
Total messages received: 29850
Success rate: 99.5%
Average latency: 12.3 ms
P99 latency: 45.7 ms
Throughput: 500 msg/s
这些数据,就是我们后面做性能优化的基准。
2.5 理解吞吐量(TPS)与延迟指标
好,数据拿到了。但你知道这些指标到底意味着什么吗?
吞吐量(TPS),全称是Transactions Per Second,每秒事务数。在ThingsBoard的场景里,一个“事务”通常指一条遥测数据从设备上报到入库的完整过程。TPS越高,说明系统处理能力越强。
延迟,指的是从设备发送数据到系统确认接收的时间差。通常我们会关注几个关键分位值:
- 平均延迟: 所有请求延迟的平均值。容易被极端值影响。
- P50延迟: 50%的请求在这个延迟以内。代表“一般情况”。
- P99延迟: 99%的请求在这个延迟以内。代表“最差情况”。
- P999延迟: 99.9%的请求在这个延迟以内。代表“极端情况”。
我见过不少团队,只看平均延迟,觉得“哎呀才10毫秒,系统性能很好嘛”。结果一查P99,发现已经飙到500毫秒了。为什么?因为平均延迟被大量的小请求拉低了,但那些慢请求才是真正的用户体验杀手。
还有一个概念叫 吞吐量与延迟的关系。你想想看,当系统负载很低时,延迟通常也很低。但随着并发量增加,延迟会逐渐上升。当系统达到某个临界点后,延迟会急剧上升,甚至导致系统崩溃。这个临界点,就是系统的“最大吞吐量”。
所以,基准测试的目的,就是找到这个临界点。比如,你测出来在50个并发客户端、每秒500条消息时,P99延迟是50ms。当并发增加到100个客户端、每秒1000条消息时,P99延迟变成了200ms。当并发到150个客户端时,P99延迟直接飙到1秒以上。那么,这个系统的安全吞吐量,大概就在每秒800-1000条消息之间。
有了这个基准数据,后面你做任何优化——调整JVM参数、优化数据库连接池、改队列配置——都能用数据说话,而不是凭感觉。
好了,这一章的内容就到这里。你手头应该已经有一个跑起来的单节点ThingsBoard,也拿到了第一份基准测试数据。下一章,我会带你深入分析这些数据,看看瓶颈到底在哪里。