1. 为什么半导体产线绕不开 SECS/GEM 通讯平台
我第一次接触SECS/GEM是在一条 8 英寸线的设备联调现场。当时最直观的感受是:设备厂商给的调试工具能手工收发几条报文,但要把它变成"能长期跑、能批量管、能对外供数"的东西,中间差着一整个通讯平台。这个平台的位置很特殊,它夹在设备和上层系统之间,往下要接几十上百台来自不同厂商、协议实现各有脾气的机台,往上要被 MES、EAP、SPC 这些系统反复调用。说白了,它不是什么炫技的东西,而是产线数据能不能稳定流动的那根管子。
很多人对 SECS/GEM 的理解停留在"一套报文规范"。这话对一半。SECS-II(SEMI E5)管的是消息长什么样,HSMS(SEMI E37)管的是消息怎么在 TCP 上跑,GEM(SEMI E30)管的是设备应该提供哪些标准能力,比如事件报告、告警、状态变量、配方管理。真正让工程师头疼的从来不是单条报文怎么编,而是:一台设备 Select 上了,另一台总是在 T7 超时;同一批设备里有的支持 S2F33 定义报告,有的必须走 S2F35;凌晨两点某台机台断线了,平台没重连,第二天早上发现数据断了六个小时。
这篇内容想做的事很明确:把"SECS/GEM 协议系统通讯平台"这个题目拆开,讲清楚平台的架构该怎么切、核心机制有哪些细节、实操时怎么一步步跑起来、以及那些调试手册上不会写的坑。它适合三类人看:刚接手设备联调的工程师、要自研或选型通讯中间件的开发者、以及需要评估平台能力边界的产线管理人员。不需要你已经是协议专家,但至少得知道 TCP 是什么、会看一点日志。
1.1 SECS/GEM 到底管什么,边界在哪里
先把概念理清楚,不然后面聊架构会飘。SEMI 标准族里,跟通讯平台直接相关的是这几份:E4 定义了 SECS-I,走 RS-232 串口,现在新设备基本见不到了,但老机台还在用;E37 定义了 HSMS,走 TCP/IP,这是当下主流;E5 定义 SECS-II 的消息内容,也就是 Stream、Function 和数据项这些;E30 定义了 GEM,是一份"设备应该具备哪些行为"的模型规范。
这里有个容易混淆的点:SECS-II 和 HSMS 是两件事。SECS-II 只关心消息体,它不在乎底下是串口还是网络。HSMS 只关心怎么在 TCP 上把一个消息完整地、可靠地送达对方,它不关心消息体里装的是什么。所以你会看到有人写"HSMS 报文解码",严格讲应该是"SECS-II 消息解码,载体是 HSMS"。
GEM 则更高一层。它规定了设备要支持哪些 Stream/Function、状态变量怎么组织、事件报告怎么定义和使能、告警怎么上报和确认。一台"GEM 合规"的设备,理论上主机用同一套流程就能完成基本的监控和控制。但"合规"这两个字弹性很大,厂商实现了哪些、没实现哪些,必须在联调前一项项确认。
平台要做的就是把这些规范落到一个可运行、可观测、可扩展的系统里。它不生产数据,它是数据的搬运工和翻译官,同时还得是个负责任的保姆——连接断了要重连,消息发丢了要重试,对方卡住了要按超时规则处理。
1.2 从单机联调到全厂组网,平台要解决的真实痛点
单台设备联调时,你用一个调试工具,手工敲 S1F13,看设备回不回 S1F14,回了就说明通讯通。这个过程很爽,因为反馈即时、上下文清楚。但一旦设备数量上到二十台以上,情况立刻变形。
第一个痛点是连接生命周期。每台设备都是一个独立的 TCP 会话,各自有 Select 状态、各自的 T3 定时器、各自的 System Bytes 计数器。你需要一个统一的会话管理器,能同时维持上百个连接,并且在某个连接异常时能独立处理,不影响其他设备。这不是难点,但如果你把连接管理写成全局单例,后面并发一上来就会到处抢锁。
第二个痛点是消息路由。平台收发的消息,要能按设备 ID 精确分发。设备发来的 S6F11 事件报告,得知道该送给哪些订阅方;上层系统下发的 S2F41 远程命令,得知道该发给哪台设备。这听起来简单,实际上设备 ID 的命名规范、大小写、别名映射经常一团糟,联调阶段最耗时的往往就是对齐命名。
第三个痛点是时序一致性。HSMS 用 System Bytes 来配对主消息和回复消息,一个平台同时开着几百个事务,如果 System Bytes 生成逻辑有问题,就会出现回复消息配错事务的情况——A 命令收到了 B 命令的回复。这种 bug 极其隐蔽,因为它不报错,只是数据错位。
第四个痛点是对外接口。MES 不想知道 SECS 是什么,它只想要一个"给我某台设备当前温度"的 HTTP 接口,或者一个"设备 X 发生告警"的消息订阅。平台必须把协议世界的复杂性封装掉,对外暴露干净的语义。
1.3 平台化之前,常见的三种做法和它们的坑
在没有统一平台的时候,行业里常见三种做法,我一个个说。
第一种是每台设备配一个独立进程。一台机器一个 exe,自己管自己的连接。好处是隔离性好,一台崩了不影响别人。坏处是运维灾难:配置文件散落各处,日志要一个个看,几十台设备就是几十个进程,升级一次要停一条线。这套做法在小试线还能撑,量产线上基本撑不住。
第二种是用设备厂商自带的通讯软件。有些设备商会提供一个 Windows 上的 GEM 主机端工具,能用。但它通常只服务自家设备,界面是给调试用的,不是给生产用的,接口能力弱,稳定性也取决于供应商的投入。L1 级联调拿来应急可以,作为长期平台不行。
第三种是把逻辑塞进 MES 或 EAP 里。早期很多厂这么干,EAP 直接开 TCP 端口跟设备对话。问题在于耦合度太高:协议层的重连、超时、重试跟业务逻辑混在一起,改一个超时参数要动业务代码,测试成本极高。而且 EAP 通常是有状态的、以工单为驱动的,跟"维持长连接、被动接收事件"这个模式天然不搭。
这几种做法的共同问题,是把协议层和业务层搅在一起。平台的第一个设计原则,就是分层。
2. 通讯平台的整体架构设计与技术选型
架构这件事,我倾向于从"数据往哪流"倒推。设备产生的数据分两类:一类是主机主动问的,比如读状态变量 S1F3;一类是设备主动推的,比如 S6F11 事件报告、S5F1 告警。前者是请求-响应模式,后者是订阅-推送模式。这两种模式对平台的要求不一样,架构上要把它们分开考虑。
2.1 分层设计:设备侧、协议侧、业务侧怎么切
我推荐的分层是这样:最底下是连接层,负责 TCP 会话的建立、维持、断开、重连;往上是协议层,负责 HSMS 帧的拆解组装、SECS-II 数据项的编解码、定时器管理、事务配对;再往上是模型层,也就是 GEM 语义层,把原始报文翻译成"设备状态""事件""告警""配方"这些业务概念;最上面是接口层,对外提供 REST、WebSocket、消息队列等接入方式。
这么切的好处是每层可以独立测试。协议层可以用模拟器喂原始字节测编解码,不需要真实设备;模型层可以喂构造好的报文测语义转换,不需要网络;接口层可以 mock 模型层。我见过太多项目把这三层拧在一起,结果联调阶段任何一个环节出问题都得全链路排查。
还有一条经验:不要在协议层的回调线程里做业务处理。HSMS 的读线程收到一条 S6F11,如果你直接在里面查数据库、调 HTTP、写文件,整条连接的吞吐立刻被拖死,严重时触发 T3 超时。正确做法是把解码后的消息丢进队列,由独立的工作线程池消费。这个坑我踩过,当时现象是"设备连上了但事件偶尔丢",查了两天才发现是读线程被数据库慢查询卡住了。
2.2 核心状态机:连接与通讯的分层状态
SECS/GEM 的状态其实是两层,很多人会混。
第一层是 HSMS 的连接状态:Not Connected、Connected / Not Selected、Connected / Selected。只有 Selected 状态下才能收发数据消息,控制消息(比如 Linktest)在 Not Selected 时也能发。
第二层是 GEM 的通讯状态和控制状态:通讯状态有 Disabled 和 Enabled,控制状态有 Equipment Offline、Equipment Online Local、Equipment Online Remote。这层状态直接影响设备行为——比如 Offline 时设备不该发事件报告。
平台需要同时维护这两层状态,并且它们的转换是有触发条件的。设备收到 S1F17(Request ON-LINE)并接受后,进入 Online 状态;收到 S1F15(Request OFF-LINE)后回到 Offline。主机侧的 UI 如果只显示"在线/离线",很容易误判,因为"HSMS 连上了但 GEM 还在 Offline"是一种很常见的中间态,此时你发 S1F3 是能收到回复的,但设备不会主动推事件。
2.3 选型对比:自研协议栈、商用库还是开源实现
这是个绕不过去的决策,我列个表对比一下,基于我参与过的几个项目经验。
| 路线 | 优势 | 代价 | 适合场景 |
|---|---|---|---|
| 全自研 | 完全可控,可深度定制,无授权成本 | 开发周期长,边界情况多,容易出现隐蔽 bug | 团队有协议专家,需求特殊,长期投入 |
| 商用协议库 | 稳定性有保障,通常附带测试工具和技术支持 | 授权费用,黑盒,定制受限 | 项目周期紧,设备种类多,需要快速上线 |
| 开源实现 | 成本低,可读源码,社区参考 | 质量参差,维护不确定,文档常缺失 | 内部工具、预研、预算有限的场景 |
我的建议是:不要一开始就全自研。先用商用库或成熟开源实现把业务跑通,把精力放在模型层和接口层,这些才是你真正的差异化价值。等到对协议理解足够深、发现现有方案确实卡住了业务,再考虑替换协议层。协议层是可以替换的,前提是你的分层做得干净。
2.4 消息建模:把 SML 变成可维护的资产
SECS-II 消息用 SML(SECS Message Language)表达最直观。平台里所有自定义消息,都应该以 SML 或等价的结构化形式存下来,而不是硬编码在代码里。举个例子,一条带列表的 S1F13:
S1F13 W <L <A "HOST_01"> <A "1.2.0"> > .把它存成配置文件或者数据库记录,好处有三个:新增设备时改配置不改代码;报文格式变更时能追溯;出错时能把实际收发的字节和期望的 SML 并排打出来对比。我做过的项目里,凡是把消息定义散在代码里的,后期维护成本都会翻倍。
3. 核心机制拆解:从 HSMS 到 SECS-II 报文
这一章讲细节,是平台能不能稳的关键。
3.1 HSMS 帧结构与粘包处理
HSMS 的帧分两部分:4 字节的长度前缀,加上消息头和数据体。长度前缀只描述后面有多少字节,不包含自己这 4 字节,这个细节新手经常搞错,导致读出来的帧永远多 4 字节或少 4 字节。
消息头固定 10 字节,依次是:2 字节 Session ID、1 字节 Stream(控制消息时是 0xFF)、1 字节 Function、2 字节 PType、2 字节 SType、4 字节 System Bytes。
TCP 是流式协议,没有消息边界。所以平台必须自己按长度前缀做拆包。标准做法是:先读 4 字节,解析出长度 L,再读 L 字节,凑成完整一帧。这里有个容易忽略的点——长度前缀本身也可能被拆包,比如你只收到 2 字节。所以读缓冲区要能处理"半条长度前缀"和"半条消息体"两种中间态。我见过有人直接用readLine之类的方式处理,遇到大报文就出问题。
注意:S6F11 事件报告里如果带了大列表,单帧可能几 KB 甚至更大。缓冲区大小要按你现场最大报文来设,并且要能动态扩展。固定 1KB 缓冲是最常见的踩坑点。
3.2 数据项编解码:格式字节与长度
SECS-II 的数据项用一个格式字节开头,里面编码了格式类型和长度信息。低几位表示类型,高位表示长度占几个字节。类型包括列表 L、ASCII 字符串 A、布尔 BO、二进制 B、有符号整数 I1/I2/I4/I8、无符号整数 U1/U2/U4/U8、浮点 F4/F8。
列表是嵌套的,所以解码天然是递归的。这部分代码我建议写成纯函数:输入字节数组和偏移,输出解析好的对象和新的偏移,不要有全局状态。这样单元测试很好写,直接喂十六进制字符串比对结果。
实际项目里最容易出问题的是字符编码。规范里是 ASCII,但有些设备的实现会用 JIS8,还有一些会用本地编码。联调时如果发现收到的字符串是乱码,先怀疑编码,别急着改协议栈。
3.3 定时器:T3、T5、T6、T7 的取值与影响
这几个定时器决定了连接的"脾气",值设错了,表现就是随机断连或者卡死。
| 定时器 | 含义 | 常见默认值 | 设置要点 |
|---|---|---|---|
| T3 | 等待回复的超时 | 45 秒 | 设备运算慢时可适当放大,但别超过 120 秒 |
| T5 | 连接分离超时 | 10 秒 | 断线检测的灵敏度,太小会误判 |
| T6 | 控制事务超时 | 5 秒 | Select/Linktest 的等待时间 |
| T7 | 未选择状态超时 | 10 秒 | 连上但没 Select 时,多久断开 |
| T8 | 字符间超时 | 5 秒 | HSMS 下基本不用,属于串口时代的遗产 |
T3 我一般从 45 秒起步,观察一周实际回复分布再调。有些设备在收到 S1F3 后要去读硬件寄存器,慢的时候能到十几秒,这时 T3 设 10 秒就会频繁超时。反过来,T3 设太大也有问题:真正卡死的连接要等很久才被发现。
T7 值得单独说。它的作用是"连上了但一直没 Select 就断开",这是防止半连接占资源的。但如果设备侧的 Select 流程比较慢,T7 太小会导致设备刚连上就被踢掉,日志上表现为"反复连接断开"。这种情况把 T7 放宽到 30 秒试试。
3.4 常用报文对与交互流程
联调和平台开发中反复用到的就那些,整理成表方便查。
| 报文对 | 用途 | 备注 |
|---|---|---|
| S1F13 / S1F14 | 建立通讯 | 只在通讯建立阶段用,之后不该重复发 |
| S1F1 / S1F2 | 在线检测 | 判断设备是否响应,常用于心跳兜底 |
| S1F3 / S1F4 | 读指定状态变量 | 需要先通过 S1F11 拿到变量清单 |
| S1F11 / S1F12 | 读状态变量命名表 | 联调第一步,确认设备支持哪些 SV |
| S1F15 / S1F16 | 请求离线 | 会改变 GEM 控制状态 |
| S1F17 / S1F18 | 请求在线 | 上线后设备才会主动推事件 |
| S2F33 / S2F34 | 定义报告 | 把若干变量组合成一个报告 |
| S2F35 / S2F36 | 报告链接到事件 | 定义哪些报告随哪个事件发出 |
| S2F37 / S2F38 | 使能/禁用事件 | 不开这个,S6F11 永远不来 |
| S2F41 / S2F42 | 远程命令 | 下发控制指令的通用通道 |
| S5F1 / S5F2 | 告警上报与确认 | 告警通常是独立于事件报告的 |
| S6F11 / S6F12 | 事件报告 | 设备主动推送的主通道 |
| S7F1 / S7F2 等 | 配方管理 | 配方上传下载,流程最长最容易出错 |
| S9Fx | 错误消息 | 收到这些说明前面某条消息有问题 |
这里有一条实操顺序,我强烈建议按这个来:先 S1F13 建通讯,再 S1F11 看变量清单,然后 S2F33 定义报告,S2F35 链接事件,S2F37 使能事件,最后 S1F17 上线。跳过任何一步,后面都会出问题。我见过有人直接使能事件但没定义报告,结果设备回了 S2F38 表示"使能成功",但 S6F11 里一个变量都没有,看着像平台解析错了,其实是链接没做。
3.5 事务配对:System Bytes 的正确用法
每条数据消息都有一个 4 字节的 System Bytes,回复消息要带同样的值。平台的发送方在发消息前生成一个不重复的值,然后把"等待回复"的事务挂到一个以 System Bytes 为键的表里。
这里有两个坑。第一是取值空间。System Bytes 是无符号 32 位,理论上够用,但如果你的生成逻辑是从 0 开始递增并且不回收,长期运行会绕回。更稳妥的做法是生成时避开当前在途的值。第二是控制消息的 System Bytes 不参与业务配对,Select.req 有它自己的值,别混进业务事务表。
还有一点:收到回复时,如果 System Bytes 在表里找不到对应事务,说明要么是超时后迟到的回复,要么是对方实现有问题。这种情况要记日志但不要崩,直接丢弃。
4. 实操:把通讯平台一步步跑起来
前面讲的都是"应该怎样",这一章讲"具体怎么做"。
4.1 环境准备与最小依赖清单
假设你用的是 Java 技术栈,最小依赖大概这些:JDK 17 以上、Netty 或 Vert.x(做异步 IO)、SLF4J + Logback(日志)、Jackson 或 Gson(配置与接口序列化)、HikariCP(如果要用数据库)。如果你选商用协议库,它通常会带自己的依赖,注意版本冲突。
我的经验是先做一个单机可跑的最小版本,不要一上来就上数据库、上消息队列、上集群。最小版本应该能做到:监听一个端口,接受一台模拟设备连接,完成 Select 流程,能收发 S1F13 和 S6F11,日志能把报文打清楚。跑通这些,后面加什么都是加法。
4.2 配置文件设计
配置不要写死在代码里。一个可用的配置结构大概长这样:
platform: listen-port: 5000 timers: t3: 45 t5: 10 t6: 5 t7: 30 reconnect: initial-delay-ms: 3000 max-delay-ms: 60000 backoff-factor: 2 devices: - id: ETCH-01 mode: passive remote-host: 10.0.1.11 remote-port: 5000 session-id: 0x0001 - id: CVD-02 mode: active listen-port: 5001 session-id: 0x0002注意几个字段。mode表示这台的连接方向:passive 是设备主动连上来,active 是平台主动去连设备。现场两种都有,平台必须都支持。session-id用常量而不是 0xFFFF,控制消息才用 0xFFFF。reconnect用指数退避,避免设备没起来时疯狂重连把网络打满。
4.3 设备侧模拟器与主机侧联调
联调阶段一定要有模拟器。自己写一个简单的 HSMS 服务端,能按脚本回消息,比等设备到货快得多。模拟器最少要实现:接受连接、处理 Select.req、对 S1F1 回 S1F2、对 S1F13 回 S1F14、能按配置周期发 S6F11。
模拟器还有一个隐藏价值:做压力测试。你可以开 200 个模拟连接,看平台的线程数、内存、CPU 是什么曲线。这一步能提前暴露很多并发问题,比上线后才发现好得多。
真实设备联调时,顺序建议是:先确认 TCP 能通(用 telnet 或 nc 测端口),再确认 Select 能过,然后是 S1F13,最后才是事件报告。每一步都确认了再往下走,不要跳。
4.4 日志与报文追踪
日志是平台最重要的功能之一,没有之一。我的标准是:每条发出的消息和收到的消息,都要有一行结构化日志,包含时间戳、设备 ID、方向、S/F、System Bytes、W-bit、以及在途事务的匹配结果。
同时准备一个"原始字节 + SML 解码"的双视图,调试时能对照看。比如:
[IN ][ETCH-01] S6F11 W sb=0x0001A2F3 S6F11 W <L <U4 1001> <U4 2002> <L <L <U4 1> <A "TEMP"> <F4 235.7>> > > .一眼就能看出事件 ID、报告 ID、变量内容。这比 hex dump 好读一百倍。日志要能按设备过滤、按 S/F 过滤,不然几百台设备的日志混在一起根本没法看。
4.5 从单台联调到批量接入的推进节奏
批量接入不要一次上。我的做法是分三批:第一批 2 台,跑通全流程,把问题都暴露出来;第二批 5 到 8 台,验证并发和资源占用;第三批全量,同时准备回滚方案。
每批上线后至少观察 48 小时,重点看三件事:连接稳定性(有没有反复断连)、事件到达率(和设备的实际动作次数对比)、资源曲线(线程数是否随连接数线性增长)。如果线程数一直涨,说明有泄漏,赶紧查。
5. 稳定性与并发:跑起来之后才是真正的开始
5.1 断线重连的设计细节
重连这件事,做对了不难,做错了一堆坑。核心原则是:每台设备的连接状态独立,重连不能共享退避状态混淆。A 设备连不上不影响 B 设备的退避节奏。
退避策略我一般用首 3 秒、倍数 2、上限 60 秒。为什么是 60 秒上限而不是更大?因为设备侧的维护窗口通常不会超过一分钟,超过一分钟的故障基本要人工介入了,重连再密也没用。上限 60 秒是个折中。
重连成功后要做的事:重新走 Select 流程、重新做通讯建立(S1F13)、重新定义并记录之前的报告订阅状态。最后这一条最容易漏。很多平台重连后连接是通的,但事件报告全停了,因为事件使能状态是设备侧的,重连后设备可能复位了。稳妥做法是重连后重放一遍订阅流程,或者至少查询当前使能状态。
5.2 并发模型与队列积压
线程模型上,我用的是"少量 IO 线程 + 中等规模工作线程池 + 每设备单队列"。IO 线程只做字节读写和帧拆解,拆完就丢队列,绝不阻塞。工作线程池负责解码、业务处理、落库。每设备一个队列的好处是天然做设备间隔离,A 设备消息洪水不会挤占 B 设备的处理能力。
队列要有上限,并且要监控。如果某个队列持续接近上限,说明消费端有问题——可能是数据库慢,可能是下游接口超时。这时候要有保护动作,比如暂停读取该设备的连接,而不是无限堆积最后 OOM。
5.3 数据落库与对外推送
落库策略要看数据量。S6F11 的频率可能很高,一台设备每分钟几十条不算多,上百台就是几千条每分钟。全量存明细的话,一天下来数据量不小。我的做法是分层:原始报文按需存(比如只存最近 7 天,用于追溯),解析后的关键字段存结构化表(事件 ID、时间、设备、关键变量),聚合指标另外算。
对外推送接口设计上,别让下游直接查库。用消息队列或者 WebSocket 推送事件,用 REST 提供按需查询。下游系统的查询模式往往很不规律,直接查库会把数据库拖垮。
6. 常见问题排查速查与避坑经验
6.1 典型故障速查表
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| 连上就断,反复循环 | T7 太小,或 Session ID 不匹配 | 放大 T7,核对双方 Session ID 配置 |
| Select 无响应 | 对端未监听,或端口被防火墙拦 | 用 nc 测端口,检查网络策略 |
| 收到消息但解析报错 | 编码不对,或长度前缀处理错 | 打印原始字节,先手工验证长度字段 |
| T3 频繁超时 | 设备处理慢,或 W-bit 未设置 | 放大 T3,确认消息真的需要回复 |
| 收不到 S6F11 | 事件未使能,或报告未链接 | 检查 S2F33/S2F35/S2F37 是否都成功 |
| 回复消息配错事务 | System Bytes 生成或匹配有 bug | 打印收发两侧的 System Bytes 对比 |
| 事件偶尔丢失 | 读线程被阻塞 | 检查是否有同步 IO 或慢查询在回调里 |
| 大报文解析截断 | 缓冲区太小 | 按现场最大报文调整缓冲,支持动态扩展 |
| S9F1/S9F7 报错 | 消息格式或设备 ID 不符 | 对着 GEM 手册核对 S/F 和数据项类型 |
| 重连后事件停推 | 设备侧订阅状态丢失 | 重连后重放订阅流程 |
6.2 我踩过的几个坑
第一个坑是长度前缀的语义。我在项目初期按"长度包含前缀自身"来实现,结果所有消息都多读了 4 字节,表现是解析出来的数据项莫名其妙。后来拿一个已知报文的 hex 一点点比对才定位。这个坑之所以难查,是因为前几条小消息碰巧能解析出看似合理的结果。
第二个坑是在回调里做同步落库。上线初期没问题,设备少。扩到三十台后开始出现 T3 超时。原因是数据库在某些时段有锁等待,读线程被卡住,导致对端等不到回复。改成异步队列后,同样负载下超时率降到零。
第三个坑是把 Session ID 当成设备唯一标识。有些厂商的设备默认 Session ID 都是 0x0001,多台接进来后冲突。平台的设备标识必须另有一套命名体系,Session ID 只是链路层的字段。
第四个坑是忽略 GEM 的双层状态。UI 上只显示"已连接",运维看到的是绿色,但设备实际在 Offline,事件一条不来。后来在 UI 上把 HSMS 状态和 GEM 控制状态分开显示,误判立刻减少了。
6.3 上线前后的检查清单
上线前我一般会过一遍这些:所有设备的 Session ID 唯一且与配置一致;T3/T5/T6/T7 按现场调过并有记录;重连后的订阅重放逻辑经过验证;日志能按设备过滤且包含 SML 视图;队列积压有监控和告警;数据库有清理任务,不会无限增长;有厂商侧的联系人,遇到协议实现差异能快速问。
上线后头一周,每天看一次连接稳定性报告和事件到达率。事件到达率这个指标特别有用,它是"设备实际动作次数"和"平台收到的事件数"的比值,比 1 低太多就说明有丢失。我做过的项目里,靠这个指标抓到过一次隐蔽的订阅失效问题。
最后分享一个我觉得挺有效的小习惯:在联调阶段维护一份"设备怪癖清单"。哪台设备不支持 S1F11、哪台必须用 S2F35 而不是 S2F33、哪台的 T3 要放到 60 秒,都记下来。这份清单在两三年后接手新设备时价值极高,因为它记录的是文档里永远不会写的东西——真实设备在真实网络里的行为。平台的功能可以抄,这份清单抄不来。