Files
msgexchange-v2/docs/reference.md
T

126 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 运行参考
本文件列出运行参数、固定调度时间、监控指标、代码位置和错误类别。业务约定见 [specification.md](specification.md),处理流程见 [implementation.md](implementation.md);其他文档引用参数时使用 `PARAM:<完整键>`
## 参数注册表
表中数值来自当前配置或代码。「暂定」表示取值还没有业务或容量依据;「与需求冲突」表示当前配置不符合验收要求。
### 收报、处理与投递
| 参数 | 默认值 | 用途与约束 | 依据 |
|---|---|---|---|
| `msgx.pipeline.poll-interval` | `1s` | 每隔多久查询一次信箱 | 沿用旧系统 |
| `msgx.pipeline.claim-batch` | `50` 条 | 一次最多从信箱读取多少条消息 | 暂定 |
| `msgx.pipeline.max-attempts` | `5` 次 | 处理或发送一条消息最多尝试多少次 | 暂定 |
| `msgx.pipeline.backoff-ms` | `[1000, 2000, 4000, 8000]` ms | 每次失败后等多久再试;等待时间档位数须比最多尝试次数少一 | 暂定 |
| `msgx.pipeline.backoff-cap-ms` | `60000` ms | 失败后最长等待时间 | 暂定 |
| `msgx.pipeline.delivery-batch` | `200` 条 | 一次最多领取多少条待发的 `msg` 消息 | 暂定 |
| `msgx.pipeline.delivery-drain-rounds` | `10` 轮 | 连续领取多少批后,先尝试发送一批 `schd` 消息 | 暂定 |
| `msgx.schd.flush-period` | `3s` | 每隔多久尝试发送一批 `schd` 消息 | 沿用旧系统 |
| `msgx.schd.flush-limit` | `500` 条 | 一批 `schd` 消息最多包含多少个航班 | 暂定 |
| `msgx.pipeline.event-retention` | `7d` | 发送成功的消息在数据库保留多久,从 `SENT_AT` 起算 | 暂定 |
### 写回信箱与编号扫描
| 参数 | 默认值 | 用途与约束 | 依据 |
|---|---|---|---|
| `msgx.pipeline.overdue-backfill` | `30d` | 入队后超过期限 `R` 仍未写回处理时间,就立即再试;若仍失败,则停止自动重试。`R` 不得长于信箱行可保证的最短保留期 | 暂定 |
| `msgx.pipeline.backfill-batch` | `100` 条 | 一次最多检查多少条待写回信箱的记录 | 暂定 |
| `msgx.pipeline.backfill-max-attempts` | `100` 次 | 失败次数达到此值时告警,仍继续重试直到期限 `R` | 暂定 |
| `msgx.pipeline.backfill-backoff-ms` | `30000` ms | 首次写回失败后等多久再试 | 暂定 |
| `msgx.pipeline.backfill-backoff-cap-ms` | `900000` ms | 以后每次重试最长等多久 | 暂定 |
| `msgx.pipeline.max-commit-delay` | `5m` | 当前按编号读信箱时,遇到缺号最多等待多久;改用处理时间筛选后删除(`G-SCAN-PREDICATE` | 待替换 |
| `msgx.pipeline.cutover-watermark` | 不设置 | 首次启动时从哪个编号开始读信箱;可填 `min``zero``max` 或具体编号;改用处理时间筛选后删除(`G-SCAN-PREDICATE` | 待替换 |
### 固定调度
下列名称只用于查阅固定时间,不能写入配置文件。
| 登记名 | 当前值 | 含义 |
|---|---|---|
| `msgx.pipeline.backfill-scan-period` | `30s` | 每隔多久检查待写回信箱的记录;不是完成时限 |
| `msgx.history.sweep-time` | `03:30` | 按机场时间每天开始清理历史航班的时间 |
### 运行开关与航班域
| 参数 | 默认值 | 用途与约束 | 依据 |
|---|---|---|---|
| `msgx.service-name` | `msgexchangeapi` | 向 Eureka 注册时使用的服务名;用于对比的新实例须使用不同名称 | 沿用旧系统 |
| `msgx.register-eureka` | `true` | 是否向 Eureka 注册服务 | 当前实现 |
| `msgx.stubs` | `true`(dev) | 是否用内存数据代替真实数据库和消息系统;只在开发环境开启 | 开发环境 |
| `msgx.pipeline.autostart` | `false` | 服务启动时是否自动读信箱、处理和发送消息 | 默认关闭 |
| `msgx.operation-day.zone` | `Asia/Shanghai` | 计算运营日(按机场规则划分的航班日期)和清理历史航班时使用的时区;填错则拒绝启动 | 沿用旧系统 |
| `msgx.operation-day.cutoff-hour` | `0` | 按机场时间几点切换运营日;业务边界尚未确认 | 暂定 |
| `msgx.identity.include-day-boundary` | `false` | 去重时是否把日期算进消息身份;受 `C-3` 约束,不能随意改变 | 默认关闭 |
| `msgx.health.backlog-cache-ttl-ms` | `30000` ms | `/health``/metrics` 共用的未处理消息统计最多缓存多久;`0` 表示每次重算 | 暂定 |
| `msgx.history.history-store-enabled` | `false` | 是否启用历史航班写入;关闭时不删除实时航班 | 默认关闭 |
| `msgx.history.cancelled-hours` | `48` 小时 | 与 `US-14` AC2 的取消航班清理条件冲突 | 与需求冲突 |
| `msgx.history.terminal-hours` | `48` 小时 | `US-14` AC2 的清理条件不包含这个等待时间 | 与需求冲突 |
| `msgx.history.deleted-hours` | `48` 小时 | 已删除航班还要等待的时间;`US-14` AC2 没有此条件 | 与需求冲突 |
| `msgx.history.idle-hours` | `168` 小时 | 长时间未更新的航班也会被清理;`US-14` AC2 没有此条件 | 与需求冲突 |
| `msgx.history.snap-log-retention-days` | `90` 天 | 日计划处理记录保存多久 | 暂定 |
### 信箱与外部依赖(成组登记)
| 参数 | 默认值 | 用途与约束 | 依据 |
|---|---|---|---|
| `mailbox.processed-value` | `PROCESSED` | 写回处理时间时,同时写入 `CMINMSGS_STATUS``Q8` 未确认这个状态值 | 当前实现 |
| `mailbox.shared-mysql.enabled` | `false` | 是否连接共享 MySQL 信箱 | 默认关闭 |
| `mailbox.shared-mysql.url` | 环境变量 | 共享信箱地址;用户名和密码也从环境变量读取 | 当前实现 |
| `mailbox.shared-mysql.connect-timeout-ms` | `3000` ms | 连接 MySQL 最长等待多久;同组读取最长等待 `socket-timeout-ms=30000` ms | 暂定 |
| `mailbox.shared-mysql.pool-connection-timeout-ms` | `5000` ms | 等待一个可用的 MySQL 连接最长多久;同组校验连接最长等待 `pool-validation-timeout-ms=3000` ms | 暂定 |
| `datasources.default.connection-timeout` | `5000` ms | 等待一个可用的 PostgreSQL 连接最长多久;同组连接校验 `validation-timeout=3000`、空闲时间 `idle-timeout=300000`、连接寿命 `max-lifetime=1800000` ms | 暂定 |
| `datasources.default.data-source-properties.connectTimeout` | `3` 秒 | 连接 PostgreSQL 最长等待多久;同组读取最长等待 `socketTimeout=30` 秒 | 暂定 |
| `kafka.producers.default.acks` | `all` | Kafka 何时确认收到消息;与下两项一起满足 `D2` | 当前实现 |
| `kafka.producers.default.enable-idempotence` | `true` | 是否避免 Kafka 生产者自身重复发送,见 `D2` | 当前实现 |
| `kafka.producers.default.max-in-flight-requests-per-connection` | `1` | 一个连接同时最多发送多少个未确认请求,见 `D2` | 当前实现 |
环境变量名见 [`.env.example`](../.env.example);其余基础设施键见 `src/main/resources/application.yml`
## 指标与健康
| 指标 | 含义 | 关注信号 |
|---|---|---|
| `msgx.pipeline.backlog.unfinished` | 尚未处理完的消息数 | 长期不降:消息越积越多 |
| `msgx.pipeline.backlog.oldest_unprocessed_seconds` | 最早收到且尚未处理的消息距今多久 | 持续增长:最早的消息一直没处理 |
| `msgx.pipeline.backfill.unmarked_terminal` | 处理已结束、但信箱还没写入处理时间的消息数 | 长期不降:写回信箱受阻 |
| `msgx.pipeline.backfill.abandoned` | 已停止自动写回信箱的消息数 | 非零:需要人工对账 |
| `msgx.pipeline.backfill.oldest_unmarked_seconds` | 最早待写回信箱的消息距今多久 | 持续增长:写回越来越慢 |
| `msgx.pipeline.job.heartbeat_age_seconds` | 上次作业成功运行距今多久 | 持续增长:作业可能已停 |
| `msgx.pipeline.job.last_failure_age_seconds` | 上次作业出错距今多久 | 结合出错次数判断故障 |
| `msgx.pipeline.job.ticks.total` | 作业成功运行的次数 | 不增长:作业可能已停 |
| `msgx.pipeline.job.failures.total` | 作业出错次数 | 增长:作业持续出错 |
| `msgx.pipeline.job.last_sweep_selected` | 上次检查找到多少条待写回信箱的记录 | 持续达到每批上限:待办太多 |
| `msgx.pipeline.codec.srvt_seen.total` | 收到含 `SRVT` 段的消息数 | 非零:核对 `G-SRVT-VIPF` |
| `msgx.pipeline.codec.vipf_seen.total` | 收到含 `VIPF` 段的消息数 | 非零:核对 `G-SRVT-VIPF` |
| `msgx.pipeline.processing.ignored.total` | 被 `IgnoreRules` 跳过的消息数 | 清单含 `REGN``RSTA``EROR`,与 `US-13``US-09` 冲突 |
| `msgx.pipeline.watermark.lag` | 信箱最新编号比已扫描编号大多少 | 改用处理时间筛选后删除(`G-SCAN-PREDICATE` |
未处理消息的统计使用同一份缓存;统计不可用显示 `NaN`,没有记录可比时年龄与编号差显示 `-1`。作业计数在进程重启后归零;作业已启动却连续三个检查周期没有成功运行时,`/health``DOWN`
## 模块与代码入口
| 关注点 | 代码入口 |
|---|---|
| 读取信箱与 HTTP 入口 | `ingress/InboxPoller.kt``ingress/InboxController.kt` |
| XML 解析 | `codec/JacksonXmlCodec.kt``codec/SisWireMapper.kt` |
| 顺序处理与航班变更 | `processing/Pump.kt``processing/DynamicProcessors.kt``processing/ScheduleProcessor.kt` |
| 写回信箱与发送 Kafka | `processing/BackfillService.kt``delivery/Dispatcher.kt``infra/kafka/KafkaDeliveryPort.kt` |
| 定时任务 | `jobs/JobRunner.kt``jobs/HistorySweepJob.kt``jobs/EventCleanupJob.kt` |
| 数据库读写与手动重试 | `infra/persistence/jdbc/``infra/retry/` |
| 配置、指标与健康检查 | `config/``infra/metrics/``infra/health/` |
## 错误分类与重放白名单
| 错误类别 | 发生情况 | 处理结果 | 修复后可手动重试 |
|---|---|---|---|
| `MALFORMED` | 找不到原文,或 XML、必要字段无效 | 立即记 `DEAD`,停止自动处理 | 否 |
| `PROTOCOL` | 整份报文未通过业务校验,或运营日不一致 | 整份不写数据库,记 `DEAD` | 否 |
| `CODEC_ERROR` | 解码程序尚不能识别报文结构 | 记 `FAILED`,等待后重试 | 是 |
| `UNSUPPORTED` | 当前没有对应的处理程序 | 当前代码记 `FAILED` 并重试;`US-03` AC2 要求跳过合法未知类型 | 是 |
| `INFRA` | 数据库、网络或程序执行出错 | 记 `FAILED`,等待后重试 | 是 |
| `EXHAUSTED` | 自动重试次数已用尽 | 记 `DEAD`;原错误类别被覆盖,原因留在 `LAST_ERROR` | 是 |
停止自动写回信箱时,记录原因 `MISSING_ROW`(信箱行不存在)或 `TRANSIENT_DEADLINE`(故障持续到期限 `R`)。两种情况都没有确认处理时间已写入;恢复和清理条件见 implementation.md「回填」。