联系管理员

开通文章发布权限

扫码 添加微信
微信图片
电话: QQ:3810899917

ufi新需求文档 2025822

1. 背景 & 目标

  • 背景:UFI 设备(4G/随身WiFi 等)需与服务器保持长连接,通过 WebSocket 实现指令下发与状态上报,并完成短信的发送/接收全流程闭环。

  • 目标
    1) UFI 端与服务器建立 ws 长连接,支持断线重连与会话恢复;
    2) 支持服务器→UFI 下发发送短信指令
    3) 支持 UFI→服务器 上报接收短信内容
    4) 服务端统一存储检索短信记录(按既定单表结构);
    5) 定义可靠传输、鉴权、安全、限速、观测规范。


2. 术语

  • UFI:终端设备,具备蜂窝网络与短信能力。

  • Server:中心服务,承载 WebSocket、任务调度与数据存储。

  • WS:WebSocket 长连接(默认 TLS,即 ws://)。

  • 上行短信 (MO):手机号→设备(设备"收到"的短信)。

  • 下行短信 (MT):设备→手机号(设备"发送"的短信)。


3. 总体架构

[UFI Device]  ←→  (WS)  ←→  [WS Gateway/Business Service][DB]
[日志/指标]
  • WS Gateway/Business Service:统一处理连接、鉴权、心跳、消息编解码、重试、速率限制、数据落库。

  • DB:PostgreSQL(按用户指定单表存储短信,见 §8)。

  • 日志/指标:Prometheus + 可视化(如 Grafana),用于可观测性(延迟/失败率/在线数)。


4. 连接与鉴权

4.1 连接地址

  • ws://<domain>/ws/ufi

4.2 鉴权方式(MD5;排除 token 字段,按 key 升序 + 约定字符串) 和之前的http 接口 一样加密md5鉴权 建议复用代码

  • 序列化:JSON。

  • 认证使用首条 auth 消息(见下节),其中:

    • 参与签名字段 = 所有业务字段的并集,但排除 token

    • 对上述字段按 key 升序 排列,拼接为 k=v 形式并用 & 连接,得到 plain

    • 计算:token = MD5( plain + "约定字符串" ),16 进制 小写 输出。

    • 时间窗:|now - ts| ≤ 300s,建议包含 nonce 防重放。

  • Server 校验步骤:
    1) 按上述规则本地重算 MD5 并比对 token
    2) 无论成功与失败都要返回。

4.3 会话建立

  • 握手成功后,UFI 立即发送 auth 消息(JSON)确认自身信息并携带签名:

    {
      "token": "xxxx", //token
      "type": "auth", // 类型
      "imei" : "xxxx"// imei
    }

  • Server 回复:code 200是成功 或 code / 其他数字是错误(携带错误码与描述)。

    {
      "code": "200", //状态 
      "msg": "success" // 信息
    }

4.4 心跳与保活

  • UFI → Server 定期发送 ping,建议 30s 一次;Server 即刻 pong

  • 服务器侧若 > 90s 未收到任何消息,判定离线并关闭连接。

  • 支持 重连恢复:UFI 重连后再次 auth,Server 可下发未完成的指令。

 


5. 通信协议(统一信封)

  • 消息格式:UTF-8 JSON,顶层字段:

    {
      "token": 1,                 // 协议版本
      "type": "<msg-type>",    // 消息类型 auth 鉴权 ping 心跳 sms_send 发送短信 sms_accept 接收到的短信
      "imei": "<imei>",          // 设备的imei
      ...
    }

  • 序列化:所有通信均使用 JSON

  • 通用约定

    • id 用于幂等(重复投递仅处理一次)。

    • 所有应答均使用 code 和 msg 字段区分是否成功和错误提示


6. 业务消息定义

6.1 设备上报:收到短信(MO,上行)

  • UFI → Serversms_accept

    {
      "token": "xxxx", 
      "type": "sms_accept", // 类型
      "imei" : "xxxx",
      "send_phone": "+861861111939",     // 发送方(手机号→设备)
      "accept_phone": "",                 // 设备自身号码(未知可空)
      "body": "【深x市市场监管局】您本次申请的验证码是X2BD9,请在2小时内使用" //短信内容 
      }
    }

  • Server → UFIsms_accept/ok

6.2 服务器下发:发送短信(MT,下行)

  • Server → UFIsms_send

    {
      "token": "xxxx",
      "type": "sms_send", //类型
      "imei": "<imei>",
      "send_phone": "",                   // 发送方 = 手机号(未知可空)
      "accept_phone": "+8613900139000",   // 接收方手机号(必填) 
      "body": "您好,这是一条测试短信",
      "sms_id": "xxxxx"  // 服务端雪花算法生成的 id 作为链路追踪 这条短信是否发送成功
    }

  • UFI 立即应答sms.send/ok(收到并排队执行),或 sms.send/err(参数错误/不可发送)。

  • UFI 执行结果回执(发送完成后):sms_send_result

    {
      "token": "xxxx",
      "type": "sms_send_result", // 类型
      "imei": "<imei>",
      "send_status": "ok" // 发送状态: 失败原因 如果成功就是 ok
      "sms_id": "xxxx" // 短信任务id 
    }

6.3 设备状态变更(可选)

  • device.status:上报信号强度、SIM 状态、运营商、网络制式等(用于策略和告警)。


7. 可靠性与限速

  • 幂等:UFI/Server 双方都应以 id 去重;发送端出现重试时复用同一 id

  • 离线缓存(UFI 侧):

    • 若离线,sms_acceptsms_send_result 先本地队列,重连后按时间顺序补发。

  • 速率限制(Server→UFI 下发):

    • 默认每张 SIM ≤ 30 条/5 分钟(可配置),超过直接 sms.send/err

  • 重试策略:网络错误或 5xx 触发指数退避(如 1s/2s/4s,最多 5 次)。


8. 数据存储(按用户“单表”要求)

仅一张表,存储所有短信收发记录(包含发送动作与接收事件),满足常用查询。

8.1 表结构(PostgreSQL)

  • 表名:sms_log

  • 字段:

    • id bigint:雪花算法生成(应用侧生成,不用 PG 自增)。 任务id 比如发短信用的此id

    • imei varchar(32):设备 IMEI。

    • type int1 设备→手机号(发送,MT),2 手机号→设备(接收,MO)。

    • send_phone varchar(32):发送方手机号,未知为空。

    • accept_phone varchar(32):接收方手机号,未知为空。

    • body text:短信内容(UTF-8)。

    • create_time int:秒级时间戳(多国家时区由展示层处理)。

    • queue int: 队列处理进度字段 服务器用的,处理短信内容的。

    • status int: 1 发短信 给ufi 0 短信已经发送成功 算是正式落库。

可选扩展(不破坏现有查询):status(0/1/2)、error_codeclient_msg_idencodingpartspart_no

8.2 索引(匹配常用查询)

-- 典型查询:imei + type + create_time(时间筛)
CREATE INDEX idx_sms_imei_type_ctime ON sms_log (imei, type, create_time DESC);

-- 典型查询:imei + type + body(内容检索)
-- 如需模糊/全文,建议 pg_trgm 或 tsvector
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_sms_imei_type_body_trgm ON sms_log USING GIN ( (imei), (type), body gin_trgm_ops );
-- 或:分开索引 + 全文列,视数据量与查询模式权衡

8.3 落库规则

  • sms_acceptsms_send_result(send_status=ok)、以及收到 sms_send 指令时即各自落一条记录

    • 接收短信(MO):type=2send_phone=<来短信号码>accept_phone=<号码或空>

    • 发送短信动作(MT 指令):type=1accept_phone=<目标号码>

    • 发送结果:同一 sms_id 可视为关联线索


9. 服务器侧功能

9.1 WS 网关 & 业务服务

  • 连接管理:上线/下线、心跳、断线清理、黑名单策略。

  • 指令队列:sms_send 下发的排队/并发控制。

  • 鉴权&权限:IMEI 与 Token 绑定;IP 黑白名单(可选)。

  • 可观测性:在线数、心跳 RTT、下发成功率、MO/MT QPS、错误分布。

9.2 后台管理接口(REST,示例)

  • 数据放在pgsql 可以通过 db 来调取数据


10. UFI 设备侧要求

  • 支持 ws、HMAC 鉴权、30s 心跳、指数退避重连。

  • 短信能力:

    • 发送:支持长短信,失败给出可读 error_code

    • 接收:即时上报,离线缓存 ≥ 100 条。

  • 队列:本地顺序队列,最多并发发送 1(默认,可配置 1~3)。

  • 日志:至少本地最近 24h 循环日志(方便现场排障)。


11. 安全

  • 默认 ws

  • 鉴权:MD5(排除 token 字段、字段按 key 升序),sign = MD5(plain + "&xxx")

  • 内容安全:通过token md5单项加密验证。


12. 性能与容量指标(SLA/SLO)

  • 单连接心跳 RTT P95 ≤ 150ms(国内);

  • sms.send 指令到 UFI 接收 P95 ≤ 500ms;

  • 日峰值:

    • 在线 UFI 设备数:≥ 50k(示例,可按实际规模调整); 服务端 协程化 1一个websocket 预计12KB 加上逻辑 一个连接 64KB

    • 短信写库:≥ 1k 条/秒(可通过批量写 + 分区提升)。

  • 可用性:月度 99.9%。


13. 监控与告警

  • 指标:在线数、重连次数、心跳超时、MO/MT 成功率、发送耗时分布、DB 写入延迟。

  • 告警:

    • UFI 心跳超时率 > 5% 连续 5 分钟;

    • MT 失败率 > 2% 连续 10 分钟;

    • DB 写入错误/延迟上升。


14. 典型时序

14.1 发送短信(Server→UFI)

Server  --sms_send-->  UFI
Server  <--ok/err--   UFI   (即时应答)
Server  <--sms_result UFI   (执行结果,成功/失败)

14.2 接收短信(手机号→UFI)

Phone -> (Carrier) -> UFI  --sms_accept--> Server  (落库)

15. 错误码建议

  • 待协商


16. 验收用例(节选)

1) 连接:IMEI+Token 正确可连,错误拒绝;断线 3 次后仍可重连。
2) 心跳:断开网络 2 分钟,Server 判定离线并清理;恢复后能自动上线。
3) MT 指令sms.send 成功/失败均有结果回执并落库;速率限制生效。
4) MO 上报:发送各类编码短信(中/英/emoji/长短信),Server 正确存储。
5) 幂等:重复的 id 不产生重复记录;重试不重复落库。
6) 检索:按 imei+type+create_timeimei+type+body 查询命中正确,性能达标。


17. 里程碑与交付

  • 待协商

评论

快捷导航

把好文章收藏到微信

打开微信,扫码查看

关闭

还没有账号?立即注册