目前全球进入人工智能、物联网、自动驾驶、5G的新一轮技术革命浪潮中,深度学习、强化学习技术使计算机在某些特定领域(例如人脸识别、AlphaZero)下实现了比人类更好的效果,物联网促进所有电子设备的互联互通,自动驾驶使汽车更加智能和安全,5G使万物互联成为可能。
很多新技术在现实中的落地应用都避免不了大量的消息实时通信,例如物联网或自动驾驶,要想实时的获取海量设备或车辆的信息并进行远程控制指令下发,频繁的断开连接是无法确保通信效率和可靠性的,尤其是自动驾驶v2x等场景,云端结合路灯、红绿灯、其他车辆的数据判定某辆车必须进行减速以避免事故时,指令下发的时效性和送达率将是致命的问题,另外还有网络信号不稳定、地库等特殊环境信号差等情况,本文将针对这些问题来研究和探讨如何构建一个支持弱网的高送达率、高时效性、高安全性、高传输效率的实时双向/多向消息传输服务。
一、需求与困难
1.需求
数据上报:
各类室内/外智能设备通过4G/Wifi以一定的频率实时上报自身信息(设备状态、GPS/高精定位、行进方向、四周环境3D建模、检测到的障碍物等)
远程监控/人工控制:
通过手机/PC等设备能查看各设备的信息(状态/环境/设备动画渲染),能远程控制智能设备执行特定工作任务(移动或预置任务)
远程自动调度:
云端进行自动的智能设备调度控制(路径规划、充电位管理、设备间避让调度、综合3d环境建模与障碍物移动检测预警/减速控制等)
2.困难
消息送达率、时效性:
目前4G/Wifi都存在信号覆盖问题,有些室内角落、地下车库,甚至室外的部分区域都会出现信号差、不稳定,甚至不可用的情况,造成上报信息和下发的指令丢失(送达率、时效性无法保证)。
5G也不是万能药,带宽解决了传输速率问题,但短时间暂时还解决不了网络延迟问题;
服务端稳定性:
设备规模预计未来可能达到千万或亿级,上报的消息频率即使按10hz计算QPS也将非常大,设计的架构需要能非常方便支持快速扩容。
消息安全性:
身份认证:需要鉴定设备的合法身份,鉴定的必要条件必须为不可复制,避免被恶意伪造模拟请求;
信息隔离:设备间消息隔离,对单设备的消息读/写授权需进行严格的控制;
传输加密:数据传输需要进行加密,避免被劫持、嗅探;
防重放:传输的消息即使出现延迟或被重放攻击也不能产生意外(例如重发一个1分钟前的控制指令,要能鉴别出且不执行);
防逆向:设备存在被恶意拆解、逆向后,需要能避免密钥等信息的泄露、或使攻击者获得伪造或访问其他设备信息的方法;
二、技术选型
1.TCP长连接
Swoole:
C语言编写的基于事件的高性能异步&协程并行网络通信引擎,提供了PHP扩展。设计思路类似nginx(Reactor)+ php-fpm(Worker)。可以创建TCP/Websocket+SSL长链接服务,支持事件驱动的同步/异步编程模式,通过集群可支持百万级长连接请求。
优点:可以使用单个全双工链接实现双向通信,内部通过异步Worker进行通信;
缺点:在业界没有超大规模应用案例;没有topic概念,需要实现消息广播、权限控制机制;
TCP长链接服务自研:
缺点:工程量较大,需要不少人力和时间;
2.MQ消息队列
通过TCP类的方案可以看到,实时同步处理对系统的并发影响较大,而消息异步处理又类似MQ消息系统,所以拿目前业界主流的MQ来看下。
一种分布式的,基于发布/订阅的消息系统,消息以Topic分类,在并发较大时通过Partition实现水平扩展,通过多个Broker组成Cluster集群实现高可用。
以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间复杂度的访问性能。
高吞吐率,即使在非常廉价的商用机器上也能做到单机支持每秒 100K 条以上消息的传输。
支持 Kafka Server 间的消息分区,及分布式消费,同时保证每个 Partition 内的消息顺序传输。
同时支持离线数据处理和实时数据处理。
Scale out:支持在线水平扩展。
缺点:
-Kafka的client较臃肿,不太适合小型终端直接使用,需要前置TCP长链接服务负责与终端通信的转发;
RabbitMQ
一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量级,更适合于企业级的开发。对路由,负载均衡或者数据持久化都有很好的支持。
缺点:同Kafka,类似的ActiveMQ不再赘述。
ZeroMQ
由C++编写的高性能异步消息库。它不是一个专用的消息 broker,而是一个可嵌入的并发框架,支持常用的各种语言,通过编写应用程序引用ZeroMQ库启动消息服务。支持pub/sub订阅模式、req/rep应答模式、push/pull单向模式。
缺点:
-缺乏完备的安全认证机制;
-非持久化队列,pub消息无sub链接时会丢弃消息;
-没有topic概念,需要实现消息广播机制;需实现WebSocket消息转发;
-缺乏完备的云端高可用方案,需自行实现集群Proxy、结合zk保障单点故障;
Redis
Redis本身支持MQ功能,可以当做一个轻量级的队列服务来使用。
缺点:数据大小>10k时响应慢的出奇;内存buffer超过配置后消费者会被强制断开连接;
3.物联网协议MQTT
一种构建于TCP/IP协议上基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,它的最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。做为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
可以看到它与Kafka等MQ思路基本类似,但针对物联网进行优化,区别主要是:
-支持Qos服务质量:0可能丢;1不丢但可能重发(送达率);2恰好一次(这个实际测试也会有重发);
-协议精简,协议交换最小化,以降低网络流量;考虑低带宽、高延迟、不稳定网络等因素;
-算力最小化,考虑客户端计算能力问题;
-支持动态创建Topic;支持层级Topic通配符订阅;
可选的稳定Broker:
-Mosquitto
业界首选的Eclipse开源Broker,实现了MQTT v5.0、v3.1协议,提供轻量级的,支持发布/订阅的的消息推送模式,适合在从低功耗单板计算机到完整服务器的所有设备上使用。
缺点:没有内置高可用集群方案,可以自行搭建;
-百度天工物接入
天工云提供的物接入MQTT服务,支持亿级并发连接和消息数,支持海量设备和云端的安全可靠双向连接。支持物模型构建、物影子(实体)上报、反向下发、权限控制等。影子topic同时支持WebSocket +SSL、MQTT+SSL、TCP方式访问。协议轻量,官方sdk或开源MQTT client支持低功耗设备。每月1亿条消息约100元左右费用还可接受。
缺点:
-单连接上报消息频率上限 QoS0:30条/秒 QoS1:10条/秒
-MQTT单个发布消息最大长度 32 KB
-设备型支持影子信息获取,但只支持json格式;
-数据型支持protobuf等任意格式,但不支持模型定义和影子信息获取,需要自己监听并cache影子数据;
4.安全
设备身份认证:
使用证书双向认证可以确保设备和云端双向身份不可伪造,配合CRL、设备黑/白名单实现设备吊销;
信息隔离:
按设备拆分消息topic,对单设备仅授予自身topic的临时读/写授权;
传输加密:
不论是MQTT还是WS,统一增加SSL对传输进行加密,避免被劫持、嗅探;
防重放:
所有消息中增加timestamp,各topic监听端对timestamp进行失效检查,以确保过期消息的业务层逻辑足够安全和合理。
防逆向:
本地存储的设备证书、密钥等开启硬件加密,防止任意读取;
本地log落盘需先进行敏感信息脱敏(删除或加密);
从整体架构设计上就隔离设备,使即使设备被劫持也不可能影响其它设备;
对各设备的异常情况进行自动入侵检测和报警,并通过云端证书吊销或黑名单禁止异常设备连接。
边缘计算:
在遇到系统安全(例如可能撞上障碍物)场景时,设备应具备自身的刹停/减速措施避免碰撞,云端仅作为全局视角的辅助调度;
三、技术方案
方案概述:
1.采用MQTT协议,传输数据采用protobuf格式进行压缩,以支持弱网Qos,满足传输效率、送达率、时效性要求,降低TCP从零实现成本;
2.采用双向认证证书+设备黑白名单+消息topic临时授权,实现设备的唯一身份鉴定与消息权限控制;
3.涉及后台、WebGl等Web端的,采用websocket+ssl+protobuf.js实现消息的收发和pb支持;
4.涉及APP等需要获取消息数据的地方,原则上自己请求授权并监听,尽可能不要增加中转环节,以提高传输效率和稳定性;
yan 20.5.8
参考:
https://github.com/protobufjs/protobuf.js