Files
msgexchange-v2/docs/architecture.md
T

8.3 KiB
Raw Blame History

架构

1. 系统定位与范围

msgexchange-v2 是机场 OMMS 的上游报文处理中间件,用于替换旧版 msgexchange-api。 它读取 CIIMS、AODB 等系统写入共享 MySQL 信箱的 XML 报文,按顺序更新航班动态,再将结果提供给下游。

本系统负责收报、解析、状态更新和结果投递,不生成上游业务报文,不替代 CIIMS/AODB,也不提供 AODB 主数据编辑能力。

  • 主要入口:轮询共享 MySQL 的 CMINMSGS
  • 兼容入口POST /cminmsgs/send,供现役兼容、手工工具和对拍使用;写入信箱后返回记录 ID,不是生产收报主路径。
  • 输出Kafka 的 msg / schd 消息、共享 MySQL 的 COUTMSGS 出站信箱,以及查询 HTTP 接口;不直接推送前端。
  • 当前范围(阶段 A:航班当前态落自有 PostgreSQL(FLIGHT_SCHD + 资源明细表 + FLIGHT_ROUTE_POINT,权威口径见 implementation.md「航班域」)。无 Redis 依赖;ES 历史投影属阶段 B。

现场供库时目标为 Oracle 11g,否则自建 PostgreSQLOracle 适配必须通过方言与集成验证后才能作为运行时选项。

本文只描述架构约束与归属,不代表能力已实现:机制见 implementation.md,前提、不变量与可声明性见 specification.md,对外契约见同文件「契约」,需求见 requirements.md,参数与代码入口见 reference.md;操作步骤在上线/切流前另立规程(设计阶段只保留前置条件与红线)。历史报文契约以 SIS 接口规范XSD 为兼容依据。

2. 总体架构

CIIMS / AODB 等上游
        │ 写入 XML
        ▼
共享 MySQLCMINMSGS
        │ 轮询未处理记录
        ▼
┌──────────────── msgexchange-v2(单实例)────────────────┐
│ ingress:发现报文 → PostgreSQL 持久化入队                │
│                         │                              │
│ processing:取 FIFO 队头 → 解析 / 去重 → 处理器决策    │
│                         └─ PG 单事务:航班变更 + 终态 + 待发事件│
│                                                        │
│ jobs:独立维护线程(回填补偿 / 历史归档 / 留痕清理)      │
│ delivery:读取 PG 待发事件 → 投递 / 重试                  │
└─────────────────────────┬──────────────────────────────┘
                          ├─ Kafkamsg / schd
                          └─ 共享 MySQLCOUTMSGS

处理结果提交后,再回填 CMINMSGS 的处理标记;失败需补偿。
查询接口读取航班动态,不参与状态写入。

收报、处理、投递与维护作业各使用独立线程,不占用 HTTP 事件循环。航班当前态的写入只发生在持有 PIPELINE_LOCK 的事务内,由主泵串行驱动。

技术栈:Kotlin + JDK 25、Micronaut 编译期依赖注入、JDBC 持久化;数据库变更由 Flyway 管理,只作用于自有 PostgreSQL。依赖版本以 build.gradle.kts 为准,不在本文重复维护。

3. 模块职责

模块 职责与边界
ingress 轮询信箱、持久化入队及兼容 HTTP 写入;不解析业务报文。
codec XML 解码,区分非法报文与可修复的解码失败。
processing FIFO 调度、业务身份绑定与去重、领域决策与落库(SCHD/FLOP/FDEL/ADFT):纯领域逻辑只返回决策;Processor 作为事务协调器,在锁事务内完成状态写入、事件与回填意图登记,不直接触碰 Kafka。
delivery 消费待发事件,负责按目标保序、schd 聚合、投递和失败重试。
jobs 回填补偿扫描、航班历史清理与留痕保留期清理;独立 job 线程执行,不参与 FIFO(与主泵的互斥见 INV-18)。
domain / config 领域状态、事件和决策模型,以及运行参数。
infra 仓储(JDBC/stub)、外部适配器、重试、健康检查与日志;通过接口隔离基础设施。

代码入口清单见 reference.md「模块与代码入口」。

4. 主流程

InboxPoller 发现 → 自有 PG 入队(INV-2)→ 主泵按最小未完成 MSG_ID 取队头、解码并按业务身份去重 → 处理器在持 PIPELINE_LOCK 的同一事务内写航班变更、待发事件、处理终态与回填意图(INV-17)→ 提交后回填共享信箱处理标记 → Dispatcher 投递 KAFKA:msgKAFKA:schd(至少一次,INV-10)。

机制细节各有归属:扫描谓词与水位、分派与事务边界、回填、保序与 schd 聚合见 implementation.md

5. 必须保持的约束

本节只列约束的归属;完整定义与验证映射见 specification.md,实现与演进不得违反:

  • 消息严格 FIFOINV-3INV-4INV-5(发现完整性依赖 PRE-2/PRE-3)。
  • 动态状态单写者与写者集合互斥:D2INV-18
  • 身份去重:INV-9
  • 快照可恢复与运营日不可变:INV-12INV-13
  • 航班当前态的物理清除只发生在历史归档之后:D1

这些约束优先于吞吐量优化。单写者降低了并发复杂度,代价是队头阻塞和吞吐上限;如需并行化,必须先重新定义顺序与状态归属,不能只调整线程数。

6. 数据归属与一致性

存储 承载内容 职责说明
自有 PostgreSQL 单行锁 PIPELINE_LOCK、处理状态与回填事实 PROC_STATE、消费水位 INBOX_CURSOR、待发事件 MSG_EVENT、请求跟踪 REQ_TRACK、航班当前态 FLIGHT_SCHD + 资源明细表 + FLIGHT_ROUTE_POINT、留痕 SCHD_SNAP_LOG 本系统唯一业务数据库。消息处理、状态推进、处理终态、回填意图与待发事件在单事务内原子提交;本地事务只在此库。记录级定义见 implementation.md「持久化记录」。
共享 MySQL CMINMSGS 入站信箱、COUTMSGS 出站信箱 外部系统所有。本系统仅执行约定的信箱读写与处理标记回填,不建表、不迁移 schema、不写历史表;由库方按 Q9 执行的清除与历史归档见 specification.md「契约」。

不使用跨库事务。 PG 事务只能保证「处理结果与待发事件一起提交」(INV-17),不能覆盖 MySQL 回填或 Kafka 发送等外部副作用。跨存储依靠幂等、重试和持久化补偿恢复;各中断位置的判定与恢复动作见 implementation.md「中断恢复」。

对外投递按至少一次设计,不承诺端到端恰好一次。Kafka 生产者幂等不能消除应用重启或 outbox 重发带来的所有重复。

7. 关键决策

仅保留仍具约束价值、且无法从正文与 implementation.md 直接推出的决策,按 D1D4 连续编号;其余曾编号条目(严格 FIFO、stub 门控、本地事务、UNSUPPORTED 处理等)已在正文以约束形式表达,不再重复列表。第三列只给证据与偏差指针;可声明性见 specification.md,决策不因状态变化而撤销。

编号 决策及理由 证据 / 偏差
D1 航班清场只在历史写入成功后进行,未接通时删 0 条;未经 FDEL 的清场须先补发删除事件。ES 历史投影(阶段 B)暂缓。 红线见 implementation.md「生命周期」
D2 动态状态单写者,生产只允许一个活动实例;多实例必须先具备可靠的排他保护。 事务行锁见 implementation.md「事务边界」;实例级排他属 PRE-5,可声明性见 CLM-6
D3 Kafka 生产要求 acks=allenable.idempotence=truemax.in.flight=1;不允许通过关闭幂等来满足生产接入。 取值见 reference.md 参数表
D4 自有库终态记录只归档到 PROC_STATE_HST,不侵入共享库的表结构或保留策略。 G-PROC-HST