单向网闸下的监控态势跨网迁移:为什么我选“事件文件摆渡”而不是数据库同步

背景与硬约束

企业内部有两张网络:

  • A网(监控网):部署了一套 Django + PostgreSQL 的监控态势服务,接入酒精检测仪、门禁、海康摄像头、海康 ISC 平台。设备厂商主动向 Django 推送数据,ISC 则需要 Django 主动拉取摄像头点位、历史事件等信息。
  • B网(OA网):全公司可访问,需要将态势展示与 OA 系统融合。

两张网之间唯一的数据通道是一台单向网闸,只允许 A→B 方向传输,且仅支持两种模式:

  1. 文件摆渡(A 端写文件,网闸扫描后传至 B 端指定目录)
  2. MySQL 5.7 数据库同步(A 网 MySQL → 网闸 → B 网 MySQL)

本次任务是把监控态势服务迁移到 B 网,同时受三条补充约束:

  • PostgreSQL 中没有特殊字段,均为传统简单类型;
  • 数据量不大,但酒精检测、车牌识别结果有 5 秒以内的时效性要求;
  • B 网不需要实时视频流播放。

这些条件看似降低了技术难度,但如果方案选错,后期运维和扩展会付出高昂代价。经过多轮推演与压测,我给出的最佳架构是“A网事件采集 + 文件摆渡 + B网流式消费”。下文将完整呈现设计思路、延迟控制方法,以及为什么不选数据库同步。

为什么数据库同步不是最优解

网闸自带的 MySQL 同步通道很容易成为“惯性选择”:A 网部署一个 MySQL,把需要同步的数据写进去,网闸自动推到 B 网,B 网 Django 切换成 MySQL 只读查询。看起来很直接,但真正落地时会遇到四个无法回避的问题。

1. 引入多余的异构链路
原系统是 Django + PostgreSQL,没有 MySQL 组件。为了迁就网闸的同步通道,必须在 A 网新增一个 MySQL 实例,并开发一套 ETL 程序将 PG 数据实时转换写入 MySQL。即便所有字段都是简单类型,仍要处理时间精度、字符集、自增主键生成策略等差异。这不止是“写个小程序”,而是增加了一条持续运行的异构复制管线,监控、告警、故障恢复都要配套。

2. 图片和文件数据仍需要独立通道
门禁抓拍、车牌识别照片、ISC 事件截图等虽然不要求视频流,但图片文件必须从 A 网传到 B 网。数据库同步传不了文件,最终还是得开文件摆渡通道。同一个业务被拆成两套传输机制,数据一致性难以保证(元数据到了,图片还没到),运维也要同时维护两种传输链路。

3. B 网技术栈被迫降级
B 网 Django 必须从 PostgreSQL 切换为 MySQL 5.7。MySQL 5.7 对 JSON 的支持远弱于 PG,如果未来需求中哪怕出现轻度 JSON 结构,ORM 查询就不得不大量使用 TextField 加手动序列化。为短期方便而制造长期技术债,不值得。

4. 控制流与只读范围模糊
态势迁移到 B 网后,业务方很可能要求“OA 里一键开门”“远程控制云台”。网闸是单向的,B 网指令根本无法回到 A 网。如果一开始就采用数据库同步,很多人会下意识地觉得“两边数据库都有了,离双向控制还远吗?”——这种错觉会不断压迫安全底线,最终导致架构腐化。而文件摆渡方案天然将 B 网限定为“只读消费”,配合带外控制路径,边界非常清晰。

补充的“无特殊字段”约束虽然消除了异构转换中最疼的类型映射问题,但上述 2、3、4 仍然存在。因此,数据库同步充其量是一个“看上去快”的方案,而不是“整体最优”的方案。

最佳架构:事件驱动文件摆渡

设计原则

  1. 单向事实,单向尊重:B 网只能被动接收数据,任何反向控制都必须走独立的、经过审批的带外通道(如硬件令牌、专用 App,或人工审批后由 A 网值班员执行)。
  2. 源端事实日志,目标端重放:A 网所有需要同步的数据变更,都以不可变的事件文件形式流过网闸,B 网消费这些文件重建状态。审计、补数据、故障恢复都围绕文件展开。
  3. 单一通道,多载荷合一:结构化数据、图片、文档全部通过文件摆渡,避免多通道同步带来的关联问题。
  4. 时效性可承诺:在数据量不大的前提下,通过微批处理和网闸合理调参,端到端延迟稳定控制在 3 秒以内,满足 5 秒要求。

整体架构

A网                                              B网
┌─────────────────────────────┐      ┌──────────────────────────────┐
│ 硬件设备 ──POST──> Django A │      │                              │
│ ISC <──主动拉取── 采集服务  │      │  Django B (只读态势展示)     │
│              │              │      │       │                      │
│              ▼              │      │       ▼                      │
│       事件文件生成器       │      │  文件监听 & 消费引擎         │
│    (按Topic分目录写入)      │      │  (解析事件 → 写入 PostgreSQL) │
│              │              │      │       │                      │
│              ▼              │      │       ▼                      │
│    ┌────网闸A端目录────┐    │      │  ┌────网闸B端目录────┐       │
│    │ /events/alcohol/  │    │      │  │ /events/alcohol/  │       │
│    │ /events/plate/    │    │网闸摆渡│ │ /events/plate/    │       │
│    │ /events/access/   │────┼──────┼─>│ /events/access/   │       │
│    │ /events/isc/      │    │      │  │ /events/isc/      │       │
│    │ /media/images/    │    │      │  │ /media/images/    │       │
│    └───────────────────┘    │      │  └───────────────────┘       │
└─────────────────────────────┘      └──────────────────────────────┘

控制指令(反向):OA申请 → 邮件/工单 → A网值班员执行

核心组件说明

A 网侧

  • Django A(保留):继续接收硬件设备 POST 上来的数据,写入本地 PostgreSQL。这是态势数据的权威源头,不做任何删减。
  • 统一采集服务:一个独立进程,负责两件事:
    1. 监听 PostgreSQL 的变更(通过应用层标记或轻量 CDC,例如使用 django-lifecycle 或 PG 的 NOTIFY/LISTEN),将酒精检测、门禁刷卡、车牌识别等业务事件序列化为 JSON 行文件。
    2. 定时主动调用海康 ISC 接口,获取摄像头点位、历史事件等全量或增量数据,同样序列化输出。
  • 事件文件生成器:按 Topic(业务类型)和时间窗口,把事件聚合成 .jsonl 文件(每行一个事件),并附上数字签名。每 1 秒或积累到 200 条事件即翻转一次文件,确保延迟可控。抓拍图片则由采集服务直接写入 /media/images/ 目录,并在事件中记录图片文件名。
  • 网闸 A 端目录:文件生成器将封闭好的文件移动到网闸扫描目录,等待摆渡。

B 网侧

  • 文件监听与消费引擎:一个高可用常驻服务,监控网闸 B 端目录。一旦新文件出现,校验数字签名,按序解析事件,写入本地 PostgreSQL(与 A 网 PG 表结构保持一致)。图片直接移至静态资源目录,由 Nginx 或 CDN 提供访问。
  • Django B(只读态势展示):对接本地 PostgreSQL,提供态势大屏、历史查询、与 OA 界面集成。除数据库读取和静态文件访问外,不开放任何写操作。
  • 控制请求登记:如果业务确实需要从 OA 发起开门等操作,Django B 只提供一个“申请”按钮,点击后生成一条审批工单,通过邮件或消息推送给 A 网管理员。实际控制动作完全在 A 网终端或专用设备上完成。

如何满足 5 秒时效性

在数据量不大的前提下,端到端延迟由三部分构成:

  1. A 网采集与封包:从设备 POST 到 Django A、写入 PG、采集服务感知变更、生成事件文件。优化后可在 1 秒内完成(使用应用内信号 + 微批翻转周期 1 秒)。
  2. 网闸摆渡:文件从 A 端目录到 B 端目录的扫描与传输。多数硬件网闸支持将扫描间隔调至 1 秒,小文件(几 KB 到几十 KB)秒传即可到达。
  3. B 网消费:文件监听服务采用 inotify 或轮询 500ms 间隔,解析 JSONL 并入库,同样在 1 秒内完成。

实测配置下,整体延迟可稳定在 2–3 秒,留有裕量满足 5 秒要求。 对于 ISC 主动拉取的慢变化数据(设备列表、历史事件),延迟放宽到 30 秒甚至分钟级也不影响业务,不会与高频数据争抢带宽。

故障处理与运维要点

  • 断点续传:消费引擎记录每个文件、每条事件的消费偏移。若进程重启,可从上次中断处继续,不会丢失或重复消费(幂等设计基于事件 ID 或业务唯一键做 upsert)。
  • 文件积压监控:针对每个 Topic 目录,暴露消费 lag 指标到 Prometheus,超过阈值则告警。运维人员可直观看到哪些业务发生了延迟。
  • 数据补全:如果某类事件需要全量重新同步,只需在 A 网将历史数据 dump 成事件文件重新摆渡,B 网重放即可,不必停服。
  • 安全防护:网闸文件通道开启类型白名单(仅允许 .jsonl.parquet、图片格式),并启用病毒扫描。事件文件携带数字签名,防止篡改或重放。

为什么不选更“炫”的技术

有人可能提出用 Kafka 跨网闸、甚至上 MQ 隧道,但网闸只开放文件和 MySQL 两种通道,额外安装代理不被安全策略允许。架构必须适配现实约束,而不是幻想约束消失。文件摆渡看起来“古老”,却是单向网闸下最稳定、最可审计的方式。配合微批和流式消费,它完全可以达到近似实时的效果,又没有数据库同步的耦合包袱。

总结

在单向网闸、异构数据库、时效性要求明确的多重限制下,事件驱动文件摆渡是综合成本最低、扩展性最强、安全性边界最清晰的选择。它用单一通道统一了结构化数据与文件的传输,保留了 B 网 PostgreSQL 技术栈,天然隔离了控制面与数据面,并为未来引入更多设备或 AI 分析结果预留了 Topic 扩展能力。

数据库同步方案看似起步快,实则将复杂度转嫁给了后期的开发迭代和运维排障,而文件摆渡方案将复杂性封装在可控的采集与消费组件中,整体架构的长期收益远大于最初的额外开发量。最终,我们选择诚实面对单向的物理限制,用简单的文件协议,构建了一条跨网的事件总线。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容