背景与硬约束
企业内部有两张网络:
- A网(监控网):部署了一套 Django + PostgreSQL 的监控态势服务,接入酒精检测仪、门禁、海康摄像头、海康 ISC 平台。设备厂商主动向 Django 推送数据,ISC 则需要 Django 主动拉取摄像头点位、历史事件等信息。
- B网(OA网):全公司可访问,需要将态势展示与 OA 系统融合。
两张网之间唯一的数据通道是一台单向网闸,只允许 A→B 方向传输,且仅支持两种模式:
- 文件摆渡(A 端写文件,网闸扫描后传至 B 端指定目录)
- 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 仍然存在。因此,数据库同步充其量是一个“看上去快”的方案,而不是“整体最优”的方案。
最佳架构:事件驱动文件摆渡
设计原则
- 单向事实,单向尊重:B 网只能被动接收数据,任何反向控制都必须走独立的、经过审批的带外通道(如硬件令牌、专用 App,或人工审批后由 A 网值班员执行)。
- 源端事实日志,目标端重放:A 网所有需要同步的数据变更,都以不可变的事件文件形式流过网闸,B 网消费这些文件重建状态。审计、补数据、故障恢复都围绕文件展开。
- 单一通道,多载荷合一:结构化数据、图片、文档全部通过文件摆渡,避免多通道同步带来的关联问题。
- 时效性可承诺:在数据量不大的前提下,通过微批处理和网闸合理调参,端到端延迟稳定控制在 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。这是态势数据的权威源头,不做任何删减。
-
统一采集服务:一个独立进程,负责两件事:
- 监听 PostgreSQL 的变更(通过应用层标记或轻量 CDC,例如使用 django-lifecycle 或 PG 的 NOTIFY/LISTEN),将酒精检测、门禁刷卡、车牌识别等业务事件序列化为 JSON 行文件。
- 定时主动调用海康 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 秒时效性
在数据量不大的前提下,端到端延迟由三部分构成:
- A 网采集与封包:从设备 POST 到 Django A、写入 PG、采集服务感知变更、生成事件文件。优化后可在 1 秒内完成(使用应用内信号 + 微批翻转周期 1 秒)。
- 网闸摆渡:文件从 A 端目录到 B 端目录的扫描与传输。多数硬件网闸支持将扫描间隔调至 1 秒,小文件(几 KB 到几十 KB)秒传即可到达。
- 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 扩展能力。
数据库同步方案看似起步快,实则将复杂度转嫁给了后期的开发迭代和运维排障,而文件摆渡方案将复杂性封装在可控的采集与消费组件中,整体架构的长期收益远大于最初的额外开发量。最终,我们选择诚实面对单向的物理限制,用简单的文件协议,构建了一条跨网的事件总线。
。