一、简介:为什么“边缘+云”必须协同?
工业 4.0 场景:
矿山井下 5G 基站、飞腾 FT-2000/4 边缘网关、PLC 控制采煤机;地面国产云(华为云 Stack、中国电子云)实时监测瓦斯浓度。
痛点:
井下→地面 800 m,光纤往返 16 ms,若直接上云控制,回环 >20 ms超 PLC 实时窗;
边缘网关算力有限,无法存 3 年全量日志,需云端冷存。
目标:
边缘侧≤1 ms控制周期;云端秒级策略下发、小时级大数据分析;链路断 10 s 可自治。
掌握“飞腾 + 实时 Linux + 国产云协同”= 国产化投标核心亮点,溢价 20%+。
二、核心概念:5 个关键词先搞懂
| 关键词 | 一句话 | 本文出现场景 |
|---|---|---|
| PREEMPT_RT | 打补丁后 Linux 支持硬实时,任务切换 <25 μs | 边缘控制器内核 |
| MQTT over QUIC | 在 UDP 上实现 0-RTT、抗丢包,适合矿山弱网 | 上行数据链路 |
| OPC UA Pub/Sub | 发布/订阅模式,1 ms 周期广播 PLC 变量 | 边缘→本地 HMI |
| Remote Manager | 国产云组件,批量 OTA 升级、容器编排 | 云端控制台 |
| 边缘自治 | 云断连后,网关降级本地模式,数据缓存本地 | 故障自愈 |
三、环境准备:10 分钟搭好协同实验台
1. 硬件
飞腾 FT-2000/4 工业网关(4 核 A55,2 GB DDR4,64 GB eMMC)×1
本地 x86 笔记本(模拟国产云)×1
千兆交换机 + 网线 ×2
2. 软件
| 组件 | 版本 | 安装源 |
|---|---|---|
| 实时内核 | linux-5.15-rt59 | 飞腾官方补丁 |
| Docker | 20.10 | apt |
| MQTT broker | EMQX 5.0(国产) | docker 镜像 |
| OPC UA | open62541 v1.3 | 源码编译 |
| Remote Manager Agent | 中国电子云 edge-agent v2.1 | deb 包 |
3. 一键装 RT 内核(可复制)
#!/bin/bash # install_ft_rt.sh wget https://github.com/phytium-dev/linux/releases/download/v5.15-rt59/linux-image-5.15.0-rt59-ft2004.deb sudo dpkg -i linux-image*.deb sudo reboot重启后:
uname -r # 5.15.0-rt59-ft2004四、应用场景:矿山瓦斯监测系统(300 字)
飞腾边缘网关运行 PREEMPT_RT 内核,通过 RS485 连接瓦斯传感器,1 ms 周期采集 CH4 浓度;本地 OPC UA Pub/Sub 将实时数据广播给井下 PLC,实现<10 ms闭环抽风控制。同时网关对 1 秒均值进行 QUIC 封装,经 5G 切片的 MQTT 主题edge/mine/gas上行到中国电子云;云端 Flink 流计算 30 秒窗口,若浓度趋势异常则通过 Remote Manager 下发“减速”指令到容器plc-ctrl。当井下→地面链路断开,网关自动切换本地 SQLite 缓存,最长存 7 天,恢复后批量续传。整套方案满足《矿山安全规程》2022 版≤1 s 告警要求,且软硬件全国产化,通过安标国家矿用产品安全标志中心初审,缩短客户审厂周期 20 天。
五、实际案例与步骤:30 分钟跑通“边缘+云”
实验拓扑:
传感器(Modbus) → FT-2000/4 网关 → MQTT/QUIC → 笔记本(云模拟)
5.1 步骤 1 - 边缘侧实时数据采集
# 1. 编译 open62541 带 Pub/Sub git clone -b v1.3 https://github.com/open62541/open62541 cd open62541 && mkdir build && cd build cmake -DUA_ENABLE_PUBSUB=ON -DUA_ENABLE_AMALGAMATION=ON .. make -j4 sudo make installC 代码(边缘发布者):
/* pubsub_gas.c */ #include <open62541.h> #include <modbus.h> // 使用 libmodbus static UA_NodeId pubNode; static UA_Double gas = 0.0; int main(void){ UA_Server *server = UA_Server_new(); UA_ServerConfig_setDefault(UA_Server_getConfig(server)); /* PubSub 配置 1 ms 周期 */ UA_PubSubConnectionConfig conn; memset(&conn, 0, sizeof(conn)); conn.name = UA_STRING("UDP-LO"); conn.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); UA_NetworkAddressUrlDataType addressUrl = {UA_STRING("127.0.0.1"), UA_STRING("4840")}; UA_Variant_setScalar(&conn.address, &addressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); conn.publisherId.numeric = 1; UA_Server_addPubSubConnection(server, &conn, NULL); /* 1 ms 循环 */ UA_Server_addRepeatedCallback(server, (UA_ServerCallback)readGas, NULL, 1, NULL); UA_Server_run(server, &running); return 0; } static void readGas(UA_Server *server, void *data){ gas = modbus_read_float(SLAVE_ID, 0x00); // 伪代码 UA_Variant val; UA_Variant_setScalar(&val, &gas, &UA_TYPES[UA_TYPES_DOUBLE]); UA_Server_writeValue(server, pubNode, val); }编译:
gcc pubsub_gas.c -o pubsub_gas -lmodbus -lopen62541运行:
sudo ./pubsub_gas5.2 步骤 2 - MQTT/QUIC 上行
# 启动 EMQX(云模拟笔记本) docker run -d --name emqx -p 1883:1883 -p 8083:8083 emqx/emqx:5.0网关安装 MQTT CLI:
sudo apt install mqttx-cli上行脚本(1 秒周期,QUIC 传输):
#!/bin/bash # upload.sh while true; do GAS=$(opcua-read -s opc.tcp://127.0.0.1:4840 -n "ns=2;i=1001" -t double) mqttx pub -q 1 -h 192.168.1.100 -t edge/mine/gas -m "{\"ch4\":$GAS,\"ts\":$(date +%s)}" \ --quic --quic-version 1 sleep 1 done5.3 步骤 3 - 云端流计算与指令下发
Flink SQL(笔记本):
CREATE TABLE gas ( ch4 DOUBLE, ts BIGINT, WATERMARK FOR ts AS ts - INTERVAL '2' SECOND ) WITH ( 'connector' = 'mqtt', 'topic' = 'edge/mine/gas', 'host' = '192.168.1.100', 'quic' = 'true' ); CREATE TABLE cmd ( speed INT ) WITH ( 'connector' = 'mqtt', 'topic' = 'cloud/mine/cmd', 'quic' = 'true' ); INSERT INTO cmd SELECT 500 -- 减速 500 rpm FROM gas WHERE AVG(ch4) OVER (ORDER BY ts RANGE BETWEEN INTERVAL '30' SECOND PRECEDING AND CURRENT ROW) > 0.5;5.4 步骤 4 - 边缘自治(断网演练)
网关脚本:
#!/bin/bash # offline_cache.sh if ! ping -c 1 192.168.1.100 &> /dev/null; then echo "offline, cache to local" sqlite3 /data/cache.db "INSERT INTO gas VALUES($(date +%s), $GAS);" else # 批量续传 sqlite3 -csv /data/cache.db "SELECT * FROM gas" | while IFS=, read ts ch4; do mqttx pub -h 192.168.1.100 -t edge/mine/gas -m "{\"ch4\":$ch4,\"ts\":$ts}" done sqlite3 /data/cache.db "DELETE FROM gas;" fi六、常见问题与解答(FAQ)
| 问题 | 现象 | 解决 |
|---|---|---|
opcua-read报 “Connection refused” | Pub/Sub 未监听 | 确认open62541编译带 UDP 多播 |
| QUIC 连接超时 | 5G 丢包 20% | 启用mqttx --quic-congestion bbr |
| 断网续传数据重复 | 主键冲突 | 云端用ts做唯一键,INSERT OR IGNORE |
| 实时抖动 > 1 ms | 看到 cyclictest Max=1500 μs | 关闭 Turbo、C-State,绑定核taskset -c 1 |
| EMQX 启动失败 | 端口被占用 | docker rm -f emqx再启动 |
七、实践建议与最佳实践
实时线程隔离
把 OPC UA Pub/Sub 线程taskset -c 1绑定,其余应用放核 0,2,3。QUIC 0-RTT 预热
首次连接后保存session ticket,断网重连省去 1 RTT。数据压缩
上行报文启用 gzip,矿山弱网 1 Mbps 场景带宽节省 60%。安全加固
云端 MQTT 开 TLS 1.3,边缘证书放 TPM 2.0 芯片(飞腾内置)。
网关防火墙只开放 8883/UDP(QUIC),禁止 22 外放。
OTA 回滚
Remote Manager 支持 A/B 分区,升级失败自动回退,满足 SIL 2 对“安全更新”要求。监控可视化
Grafana 模板 ID15261专门显示“边缘→云”延迟,5 分钟导入即用。
八、总结:一张脑图带走全部要点
飞腾 + 实时 Linux + 国产云协同 ├─ 边缘:PREEMPT_RT + OPC UA Pub/Sub 1 ms ├─ 上行:MQTT over QUIC 抗丢包 ├─ 云端:Flink 流计算 30 s 窗口 ├─ 自治:SQLite 缓存 + 断网续传 └─ 运维:TPM 安全 + OTA A/B 回滚“国产芯 + 实时系统 + 自主云”三位一体,让你在能源、矿山、轨道交通等关键领域既有硬实时,又有软协同,投标写“全国产化安全可控”不再空喊口号。
立刻把pubsub_gas.c复制到飞腾板卡,跑通第一条 1 ms 数据流,再打开 Grafana 看曲线——边缘与云的距离,原来就是一条 QUIC 连接!