数蛙科技百亿级物流标签轨迹时序数据压测
压测背景**:**LPWAN 是当前物联网行业中最重要的技术之一,以年复合增长率 90%的惊人速度增长。NB-IOT、LoRa、ZETA 以及 Sigfox 是当前市场上主流的几种 LPWAN 通信技术。
ZETA LPWAN 协议以超窄带、低功耗双向通信和多跳组网的特点,彻底改善了传统的 LPWAN 协议不足之处,大大增加了 LPWAN 技术在物联网应用的空间。
ZETag 云标签是纵行科技基于 ZETA 技术开发的传感柔性标签,具有公里级超广覆盖,低功耗特性等优势,与同类技术相比,成本可降低至 1/3-1/10,并能支持大容量并发,使用寿命最长可达 5 年。与此同时,ZETag 云标签通过减小尺寸和功耗并改善性能来消除常规有源标签的闲置,除却物流仓储和货物追踪,还可作为一次性标签广泛应用在资产定位和危化、危废管理的万亿级市场。
目前,ZETag 云标签已在京东物流、中国邮政、日邮物流、上海睿池、上海派链等上下游物流企业物流载具及贵重包裹上实现应用,也是全球首例在速递邮件上实现实时轨迹跟踪的服务的物联网云标签。
数蛙科技是工业物联网千万级设备接入与管理的专业平台提供商,目前业务场景已覆盖电力、交通、物流、工业制造等多领域的商业应用。
涛思时序数据库 TDengine 是目前针对物联网时序数据库,性能最优的开源数据库平台,广泛运用于工业、电力、车联网、大数据领域。核心性能较其他数据库普遍快 10 倍以上,且拥有强大的全栈配套工具,如 MQ、缓存、流式计算等成熟工具链。
纵行科技是国内物联网通信 ZETA 技术的发起者,合作伙伴超 500 家,业务覆盖 20+国家。其中 ZETag 标签在物流领域具有极强的竞争力,拥有同类技术的 1/10 的低成本优势,目前已在国内众多物流巨头客户落地,产生了巨大的商业价值。
数蛙科技结合纵行科技的 ZETag 云标签与涛思数据的高容量时序数据库,为物流领域未来高增长、高并发的物流标签场景,进行了 1000 万接入、百亿级时序数据的运营级全业务模拟压力测试。
ZETag 物流标签组网如下:
压测目的**:**本次压力测试通过模拟 1 万 ZETA AP、千万 ZETA TAG 标签的在线运行,精准高效完成 ZETA AP、ZETA TAG 的在线协议解析、解析数据实时入库、海量数据在线查询与展示等流程。同时,对真实物流业务场景进行抽象,实现批次 ZETA TAG 在不同线路上发生轨迹改变,移动过程中利用不同的 ZETA AP 实现定位。ZETA TAG 在线运行过程中,每隔 15 分钟发送心跳包,被临近的单个或者多个 ZETA AP 报送至服务端。服务端会按照策略选择信号最好的上报数进行存库,并利用上报信号最好的 AP 对 ZETA TAG 进行定位。
通过压力测试,判断当前应用环境情况下系统的负载能力,为今后应用范围扩大,用户量上升后,服务器扩容、升级等提供必要的技术支撑,及服务器规划等。
本次测试目的是为了验证基于数蛙连接与设备管理平台的 ZETA 物流跟踪管理能够实现千万级 ZETA TAG 标签同时在线稳定运行、数据及时回传、正常入库、高效查库。
本次测试场景的压力与复杂度远高于真实场景,在保障 ZETA 物流跟踪当前业务可以正常开展的同时,也可以有效支撑 ZETA 相关业务应用的拓展与深化应用。
压测环境由于压力测试是对系统负载能力的测试,无法通过真实的环境来进行获取相关指标,因此通过测试机与测试服务,模拟 1 万 AP、千万 ZETA TAG 与服务器高频数据交互,利用算法虚拟真实业务场景下实际的操作来进行测试。
测试机部署虚拟云设备服务,及进行压力测试的客户端机器,一般采用高配置的机器来进行测试。在压力测试过程中,一般忽略测试机对压力测试结果的影响。
服务端:
硬件配置
服务器类型
腾讯云服务器
处理器
12 核 CPU 2.0GHz
内存
48G
硬盘
500G
……
操作系统
LINUX centos7.3 64 位
数据库系统
Tdengine 1.6.3 应用软件
连接平台+应用服务器+数据库服务器 测试机:
硬件配置
服务器类型
腾讯云服务器
处理器
4 核 CPU 2.0GHz
内存
8G
硬盘
200G
……
操作系统
LINUX centos7.3 64 位
应用软件
虚拟基站+虚拟卡车+虚拟 Zeta 标签
压测场景
ZETA 设备运行模拟:
ZETA AP:每 10s 主动连接服务端,连续 30min 未连上等待 2min 再次连接;连接状态下 1min 一次心跳交互;连续三次未收到 ACK,发起重连。
ZETA TAG:每 15 分钟上报一次心跳包;心跳报文被不同 AP 接收上报后,服务端会比较后保留首次 收到 TAG 心跳后 3s 内 RSSI 最强上报的 AP 位置信息作为 TAG 的当前位置。
客户端场景模拟描述:
运输、配送线路:本次场景模拟线路总计 200 条,线路可以配置。
运输车辆:本次场景模拟运输车辆 50000 部,货车会模拟真实物流场景在既定线路上进行移动,车上 ZETAG 标签随之移动。
ZETA AP:本次模拟 10000 台,每条线路上分布 500 台 ZETA AP
ZETA TAG 数量:本次模拟在运 ZETAG1000 万个,ZETAG 随运输车辆移动,每隔 15 分钟的心跳报文被相邻的 2-3 个 ZETA AP 接收。
服务端业务描述:
1、每 15 分钟内完成千万在运 ZETAG 标签心跳数据包解析(加上冗余报文,每 15 分钟内解析心跳报文数量 2000 多万条);
2、完成 ZETA TAG 心跳数据比较与冗余数据过滤;
3、完成解析出的海量 TAG 位置信息实时分类入库;
4、支持 ZETA TAG 最新位置更新与轨迹查询;
5、每分钟完成 1 万 ZETA AP 的心跳报文解析、存储;
6、完成 ZETA AP 运行状态信息的接收与存储;
7、支持 ZETA AP 运行状态信息查询。
根据测试系统中消息的业务场景情况,选取以下指标作为场景压力测试情况判断依据:
A、ZETA AP 在线情况统计
B、ZETA AP 在线率
C、在线 ZETAG 标签数量
D、ZETA 标签解析包数量
E、1/5/15 分钟 CPU 平均负载
F、内存使用量
压测技术系统监控服务端与客户端系统监控和业务数据监控采用 Prometheus&Grafana 做统计与展示
时序数据监控 --- Grafana&TDengine 监控插件(监控 TDengine 数据总量、丢包数以及增长速率)
系统指标监控 --- Grafana&&Prometheus 监控插件,用 node_exporter 采集数据(监控 CPU,内存,网络、存储四大指标)
业务消息监控 --- Grafana&Prometheus 监控插件,业务层通过 Prometheus client 实时统计各个消息路由节点上发包数、收包数以及丢包数等指标,业务层主要指标如下:
{ "name": "ap","help": "ap 数量","type": "counter","labels": ["from"]},{ "name": "tag","help": "tag 的包数量","type": "counter","labels": ["from"]},{ "name": "zetag","help": "zetag info","type": "gauge","labels": [ "status" ]}]
[{ "name": "shuwa_group_metrics","help": "数蛙任务调度与消息汇聚消息统计","type": "counter","labels": [ "di","tid","rid","cid","type" ]}]
时序数据 ZETag 物流标签的地址域是 4 个字节,最高的一个字节是保留字节,本次压测的 ZETag 物流标签的实际地址域是 3 个字节,所以 ZETag 地址为 FF XX XX XX,总计 16,777,215 个标签的地址,如果按照一个标签设备一个子表的方式设计,需要 1600 多万个子表。根据实测结果,Tdengine 1.6.3 单机版本子表数量超过 49 万就极不稳定,很容易崩溃,但子表数量在 10 万以下具有良好的性能。所以子表设计采用了一种虚拟分组设计,将最低两个字节(总计 65,535 个子表)作为子表空间,每个子表存储一个字节(总计 255 个标签)的标签时序数据。
时序数据模型设计:
zetag() -> #{ <<"stable">> => #{ <<"database">> => <<"t">>,<<"stable">> => <<"t">>,<<"tags">> => #{ <<"zetag">> => shuwa_tdengine_bridge_dialect:binary(2)},<<"value">> => #{ <<"ts">> => shuwa_tdengine_bridge_dialect:timestamp(),<<"zetagid">> => shuwa_tdengine_bridge_dialect:binary(4),<<"timetolive">> => shuwa_tdengine_bridge_dialect:int(),<<"lat">> => shuwa_tdengine_bridge_dialect:float(),<<"long">> => shuwa_tdengine_bridge_dialect:float(),<<"version">> => shuwa_tdengine_bridge_dialect:tinyint(),<<"status">> => shuwa_tdengine_bridge_dialect:tinyint(),<<"rssi">> => shuwa_tdengine_bridge_dialect:float()}},<<"table">> => #{ <<"type">> => <<"function">>,<<"mod">> => <<"shuwa_zeta_model">>,<<"function">> => <<"zeta_tag_subtable">>,<<"args">> => #{ <<"database">> => <<"t">>,<<"stable">> => <<"t">>,<<"tags">> => [<<"FF">>]}}
}.
240 亿数据存储空间占用 230G 磁盘空间
数据存储目录
时序数据入库示例:
-module(shuwa_td_test).-author("shuwa").-export([rand_tag/0, t/0]).rand_tag() -> integer_to_binary(4278190080 + round(rand:uniform() * 16777215), 16).t() -> shuwa_tdengine_format:insert_zeta( #{ <<"zetagID">> => rand_tag(),<<"times">> => 1,<<"lat">> => 2,<<"long">> => 3,<<"version">> => 4,<<"status">> => 5,<<"rssi">> => 6,<<"ts">> => shuwa_utils:now_ms()}).
本次模拟了 1300 多万的物流标签 15 分钟一个心跳,平均 1.4 万多的 QPS,峰值 QPS 很容易超过 Tdengine 的入库 QPS 阀值,导致 Tdengine 崩溃。在消息路由层设计了一个基于令牌桶算法的消息缓存层进行削峰处理,在保证时序数据的顺序性的同时,也能让时序数据以比较平稳的速率批量入库。由于 Tdengine 没有提供 erlang 的连接池程序,最开始用默认的 http 客户端来入库,长时间运行不稳定,最后我们把 Tdengine 原生的 c 语言的连接池程序进行了改造,添加了 mqtt 订阅功能,通过 mqtt 协议来转发批量存库时序数据。
时序数据出库策略:
由于对子表进行虚拟分组设计,查找任何一个物流标签数据的物流轨迹数据都有非常便捷的寻址算法,快速查找到用户层期望的时序数据,在百亿级数据规模的情况下,查询速度也可以到毫秒级。
ZetaEtag 即时数据查询接口:/zeta/etag/{tag}
超时时间为 5 秒
随机读 tag,数据库内数据 58169933 条
tag 生成方式:FF 开头后六位随机生成
请求次数/次
200000
测试总时间/秒
269.583
返回 200 数
120116 / 200000
返回 404 数
79884 / 200000
返回其他状态码
0 / 200000
返回成功率 / %
100
每秒请求数 / 次/秒
741.88
返回 status code 为 200(找到目标 tag)或 404(找不到目标 tag)两者都视为调用成功
ZetaEtag 历史数据接口:zeta/etag/history/{tag}
超时时间为 5 秒
对所有 tag 随机读,limit 值为 100,日期范围在合理范围内随机产生,数据库内数据 58169933 条
tag 生成方式:FF 开头后六位随机生成
日期生成方式:1569558137~1569579737 间随机数
请求次数/次
200000
测试总时间/秒
298.123
返回 200 数
200000 / 200000
返回其他状态码
0 / 200000
返回成功率 / %
100
每秒请求数 / 次/秒
670.86
2019 年 10 月份做压测报告时,没有记录 240 亿时的 API 统计,把去年的压测镜像恢复回来,240 亿标签数据时的查询速度如下
消息路由 ZETag 物流标签数据从数据产生到数据落库,1300 多万 ZETag 标签 =》5 万卡车进程=》1 万 AP 基站客户端连接进程=》1 万 AP 的服务端连接进程=》65535 虚拟分组进程=》消息缓存调度进程 =》Tdengine 的 mqtt 客户端=》Tdengine 连接池存储进程,消息需要经过 7 次转发,每一跳都需要小心处理内存释放和消息堵塞问题。每 15 分钟有将近 3000 万-4500 万消息的生产和消费,需要有非常好的 GC 处理机制。其中 1 万 AP 的服务端连接进程--》65535 虚拟分组进程,这一跳消息转发速率没有固定的对应关系,两点之间 QPS 波动非常大,用开源的 mqtt 消息转发和消费组策略也非常容易导致消息堵塞和内存持续上涨。这里也还是得益于之前的虚拟分组设计,通过虚拟分组比较好的解决了这一跳的高效消息路由,同时也把这两点之间的消息转发的 QPS 峰值削的比较平。
影子设备本次测试模拟的是类似双 11 这样的物流标签轨迹最繁忙的场景,模拟了 5 万台卡车装满(200 多件贴上 ZETag 标签的快递件)快递件,在 200 多条线路上飞奔,在行驶过程中不停切换 AP 基站,上报 ZETag 标签轨迹数据,满怀期望的用户时不时登录快递网站查看一下自己购买的货物到了何处。我们在系统中设计了 5 万个卡车影子设备,1 万的 AP 基站影子设备和 65535 虚拟分组影子设备来处理这一较为复杂的业务场景。卡车影子设备承载了 ZETA 标签信息,线路位置信息和线路沿途的 AP 基站信息的交互,AP 基站影子设备承载了 ZEtag 通信协议处理,虚拟分组影子设备承担了 1300 万 ZETag 标签的边缘计算和时序数据存储处理。
任务调度每 15 分钟有将近 3000 万-4500 万 ZETag 标签消息的生产和消费除了需要良好的 GC 机制,同时也需要一个良好的任务调度机制。治大国如烹小鲜,每一个影子设备上面的任务调度处理细节非常关键,每一个小的偏差都会被乘以一个 3000-45000 万的系数放大,对任务调度质量要求是零缺陷。合理的分组策略(也即合理的影子设备设计)非常关键,可以从宏观上对系统资源进行削峰,在单个影子设备上进行完美的微操作,让每一个影子设备的任务调度策略达到零缺陷。
压测结果
参考网站:
纵行科技:https://www.zifisense.com/
涛思数据:https://www.taosdata.com/
欢迎大家底部留言,一起探讨物联网科技的魅力所在。————————————————版权声明:本文为 CSDN 博主「DGIOT」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/DGIOT/article/details/114921294
版权声明: 本文为 InfoQ 作者【dgiot】的原创文章。
原文链接:【http://xie.infoq.cn/article/d4ec76783b6043f4b8b42e467】。文章转载请联系作者。
评论