Files

119 lines
11 KiB
Markdown
Raw Permalink 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.
# 参考注册表:参数、指标、代码入口、错误分类
本文件是**可派生事实**的唯一出处:参数默认值、指标名、模块与代码入口、错误分类。正文只引 `PARAM:<完整键>`,不写数值。
维护规则:新增或改名一个 `msgx.*` 键、增删一个指标名,必须同步本文件(人工核对,本项目不做 CI 校验)。`mailbox.*``datasources.*``kafka.*` 属基础设施键,成组登记。
## 1. 参数注册表
「依据」列含义:**契约** = 由 [specification.md](specification.md) 的 `C-x` 决定;**现役** = 沿用 legacy 行为基线;**假定** = 无依据的占位值,必须在对应 `Q` 关闭后重评;**安全默认** = 关闭态,需显式开启。
### 1.1 管道节奏与重试(`msgx.pipeline.*`
| 参数 | 默认 | 单位 | 依据 | 说明 |
|---|---|---|---|---|
| `msgx.pipeline.poll-interval` | `1s` | Duration | 现役 | 收报轮询节奏;决定队头检查频率 |
| `msgx.pipeline.claim-batch` | `50` | 条 | 假定 | 单轮领取上限;过大延长单轮事务 |
| `msgx.pipeline.max-attempts` | `5` | 次 | 假定 | 处理与投递共用;达到即转 `DEAD(EXHAUSTED)` |
| `msgx.pipeline.backoff-ms` | `[1000,2000,4000,8000]` | ms / 档 | 假定 | **档位数必须 = `max-attempts 1`**,启动自检拦截错位 |
| `msgx.pipeline.backoff-cap-ms` | `60000` | ms | 假定 | 单档封顶;默认表内无档触及 |
| `msgx.pipeline.max-commit-delay` | `5m` | Duration | **假定(无依据)** | **待退役**:水位空洞老化阈值,随收报改谓词扫描(`G-SCAN-PREDICATE`)删除;依据 `C-2` 已作废 |
| `msgx.pipeline.overdue-backfill` | `30d` | Duration | 契约(`R ≤ R_keep` | 即 `R`:进入强补写窗口、**取消退避**的阈值;**不是兜底保证** |
| `msgx.pipeline.backfill-batch` | `100` | 条 | 假定 | 回填扫描单批条数 |
| `msgx.pipeline.backfill-scan-period` | `30s`(代码常量,无配置键) | Duration | 现役 | 回填扫描作业周期 |
| `msgx.pipeline.backfill-max-attempts` | `100` | 次 | 假定 | 单行重试的**告警阈值**;放弃判据是 `R` 超期,不是次数 |
| `msgx.pipeline.backfill-backoff-ms` | `30000` | ms | 假定 | 回填独立退避起步间隔;`BackfillService` 指数退避的首档 |
| `msgx.pipeline.backfill-backoff-cap-ms` | `900000` | ms | 假定 | 回填退避封顶(15 分钟) |
| `msgx.pipeline.cutover-watermark` | 不设置 | `min\|zero\|max\|<id>` | 一次性运维决策 | **待退役**:显式播种水位(`G-SCAN-PREDICATE`);非法值由启动自检挡下,升级实例拒绝重新播种 |
| `msgx.pipeline.delivery-batch` | `200` | 条 | 假定 | `KAFKA:msg` 每轮每目标领取上限 |
| `msgx.pipeline.delivery-drain-rounds` | `10` | 轮 | 假定 | 连取批数上限,让出循环跑 `schd` flush,防状态通知被积压饿死 |
| `msgx.pipeline.autostart` | `false` | 布尔 | 安全默认 | 启动即拉起收报 / 主泵 / 投递循环;需真实仓储或 `msgx.stubs=true` |
| `msgx.pipeline.event-retention` | `7d` | Duration | 假定 | 已 `SENT` 事件行保留期,由清理作业删除 `sent_at < now - retention` 的行 |
### 1.2 其它 `msgx.*`
| 参数 | 默认 | 依据 | 说明 |
|---|---|---|---|
| `msgx.service-name` | `msgexchangeapi` | 契约冻结 | 服务注册名;影子实例用独立名 |
| `msgx.register-eureka` | `true` | 现役 | 服务注册开关;影子对拍期置 `false` |
| `msgx.stubs` | `true`dev profile | 安全默认 | 内存适配器;**生产禁止**,生产 profile 不设置该键 |
| `msgx.schd.flush-period` | `3s` | 现役 | `schd` 聚合周期 |
| `msgx.schd.flush-limit` | `500` | 假定 | 聚合批上限 |
| `msgx.operation-day.zone` | `Asia/Shanghai` | 现役 | 运营日推导时区;配置值非法时启动失败,不使用代码字面量回退 |
| `msgx.operation-day.cutoff-hour` | `0` | **假定(占位)** | 切日边界;待业务确认 |
| `msgx.identity.include-day-boundary` | `false` | 安全默认 | 身份是否加日期边界;影响去重语义,不能当调优项切换(`Q10` |
| `msgx.health.backlog-cache-ttl-ms` | `30000` | 假定 | 积压快照缓存窗口;`0` = 不缓存;`/health``/metrics` 共用同一快照 |
| `msgx.history.history-store-enabled` | `false` | 安全默认 | 历史存储门控;关闭时历史清理删 0 条 |
| `msgx.history.cancelled-hours` | `1` | 假定 | 历史清理的取消态判据窗口 |
| `msgx.history.terminal-hours` | `48` | 假定 | 历史清理的终态判据窗口 |
| `msgx.history.deleted-hours` | `48` | 假定 | 历史清理的已删除判据窗口 |
| `msgx.history.idle-hours` | `168` | 假定 | 历史清理的静默期判据 |
| `msgx.history.snap-log-retention-days` | `90` | 假定 | `SCHD_SNAP_LOG` 保留天数 |
### 1.3 信箱与外部依赖(成组登记)
| 参数组 | 默认 | 依据 | 说明 |
|---|---|---|---|
| `mailbox.processed-value` | `PROCESSED` | 契约(`C-5``Q8`) | 处理标记写入值;仅限库方认可值集 |
| `mailbox.shared-mysql.enabled` | `false` | 安全默认 | 真实信箱接线门控 |
| `mailbox.shared-mysql.connect-timeout-ms` | `3000` | 假定 | 有界外部调用;Connector/J 默认无限等待,必须显式;同组 `socket-timeout-ms=30000` |
| `mailbox.shared-mysql.pool-connection-timeout-ms` | `5000` | 假定 | 池级连接超时;同组 `pool-validation-timeout-ms=3000` |
| `mailbox.shared-mysql.url` | 环境变量 | 安全 | 零入库,见 `.env.example`;同组 `username` / `password` |
| `datasources.default.connection-timeout` | `5000` | 假定 | 自有 PG 池(毫秒数,非 Duration 字面量);同组 `validation-timeout=3000``idle-timeout=300000``max-lifetime=1800000` |
| `datasources.default.data-source-properties.connectTimeout` | `3` | 假定 | 驱动级连接超时(秒);同组 `socketTimeout=30` |
| `kafka.producers.default.acks` | `all` | 契约(`D2` | 允许环境变量覆盖 |
| `kafka.producers.default.enable-idempotence` | `true` | 契约(`D2` | 允许环境变量覆盖 |
| `kafka.producers.default.max-in-flight-requests-per-connection` | `1` | 契约(`D2` | 启动自检钉住三项联合满足 `D2`;允许环境变量覆盖 |
环境变量清单以 `.env.example` 为准。
## 2. 指标与健康
| 指标 | 含义 | 期望方向 |
|---|---|---|
| `msgx.pipeline.backlog.unfinished` | 未处理完的消息条数 | 长期 > 0 且不降 → 积压 |
| `msgx.pipeline.backlog.oldest_unprocessed_seconds` | 最老未处理消息的信龄 | 持续增长 → 队头卡住 |
| `msgx.pipeline.backfill.unmarked_terminal` | 已终态但未打标的条数 | 不降 → 回填失败 |
| `msgx.pipeline.backfill.abandoned` | 已放弃自动回填的条数 | **非 0 需人工对账** |
| `msgx.pipeline.backfill.oldest_unmarked_seconds` | 最老待回填年龄 | 决定实际回填延迟 |
| `msgx.pipeline.watermark.lag` | 水位落后信箱最新 ID 的距离;**待退役**(`G-SCAN-PREDICATE` | 增长 → 收报停滞 |
| `msgx.pipeline.job.heartbeat_age_seconds` | 距上一次作业 tick 完成的秒数(未跑过为 -1) | 持续增长 → 作业线程卡死 |
| `msgx.pipeline.job.last_failure_age_seconds` | 距最近一次作业 tick 失败的秒数(从未失败为 -1) | 配合 `failures.total` 增长判断扫描/历史作业异常 |
| `msgx.pipeline.job.ticks.total` | 作业 tick 完成次数 | 不增长 → 作业停摆 |
| `msgx.pipeline.job.failures.total` | 作业 tick 抛错次数 | 增长 → 扫描/历史作业异常 |
| `msgx.pipeline.job.last_sweep_selected` | 上一轮回填扫描选中的待办条数(扫描积压) | 持续顶到批次上限 → 扫描吃不消 |
| `msgx.pipeline.codec.srvt_seen.total` | 入站记录中出现 `SRVT` 段的条数(`G-SRVT-VIPF`) | > 0 → 真实流量确有该段,按真实报文定案 `Q11` |
| `msgx.pipeline.codec.vipf_seen.total` | 入站记录中出现 `VIPF` 段的条数(`G-SRVT-VIPF` | 同上 |
| `msgx.pipeline.processing.ignored.total` | 命中 `US-04` 忽略清单的报文条数 | 增长是正常流量;归零反而需确认配置是否丢失 |
取数规则:统一走 `BacklogSnapshotProvider``PARAM:msgx.health.backlog-cache-ttl-ms`),`/health``/metrics` 共用同一快照——`backlog()``PROC_STATE` 的全表聚合,不能被高频抓取打穿;**无法取数上报 `NaN`,无可比记录的年龄/滞后类仪表上报 `-1`,都不伪造 0**。日志出口故障不得阻塞业务线程。进程内计数类指标不经快照,重启归零。
作业健康:回填的唯一驱动是扫描作业,因此作业存活必须独立可观测——`msgx.pipeline.job.heartbeat_age_seconds` / `ticks.total` / `failures.total` 是作业心跳,`msgx.pipeline.job.last_sweep_selected` 是扫描积压,`msgx.pipeline.backfill.oldest_unmarked_seconds` 是实际回填延迟;作业线程停摆由 `/health` 的作业指示器判 `DOWN`(心跳超过 `3 × 扫描周期`,周期是代码常量)。
## 3. 模块与代码入口
| 关注点 | 主要入口 |
|---|---|
| 收报与兼容接口 | `ingress/InboxPoller.kt``ingress/InboxService.kt``ingress/InboxController.kt` |
| 解码与忽略规则 | `codec/JacksonXmlCodec.kt``codec/XmlCodec.kt``codec/SisWireMapper.kt``codec/SisMessageBody.kt``processing/IgnoreRules.kt` |
| 调度与处理 | `processing/Pump.kt`(含 `MessageProcessor`)、`processing/DynamicProcessors.kt`FLOP/FDEL/ADFT)、`processing/ScheduleProcessor.kt``processing/Identity.kt``processing/MessageLifecycleGate.kt` |
| 回填与投递 | `processing/BackfillService.kt``delivery/Dispatcher.kt``infra/kafka/KafkaDeliveryPort.kt` |
| 维护作业 | `jobs/JobRunner.kt``jobs/HistorySweepJob.kt``jobs/EventCleanupJob.kt``infra/persistence/SnapshotLogPurge.kt` |
| 持久化与恢复 | `infra/persistence/`(含 `jdbc/JdbcPgRepositories.kt``jdbc/JdbcCminmsgInboxRepository.kt`)、`infra/retry/``ProcFailure` / `ReplayService` / `FailureScheduler` |
| 启停与配置 | `PipelineLifecycle.kt``config/PipelineProps.kt``config/HistoryProps.kt``config/OperationDayProps.kt`(含运营日时区启动自检)、`config/MailboxProps.kt``config/KafkaD3Check.kt``D2` 三联合启动自检) |
| 指标与健康 | `infra/metrics/PipelineMetrics.kt``infra/metrics/JobActivity.kt``infra/health/BacklogSnapshotProvider.kt``infra/health/JobRunnerHealthIndicator.kt` |
| 迁移 | `src/main/resources/db/migration/`(单基线 `V1__flight_state_baseline.sql``oracle11g/` 为占位) |
## 4. 错误分类与重放白名单
| 错误类别 | 触发 | 处置 | 可重放 |
|---|---|---|---|
| `MALFORMED` | 报文非法、原文缺失或缺少该类型必需的业务载荷 | 立即 `DEAD` | 否 |
| `PROTOCOL` | 载荷存在但整包违反业务协议(运营日冲突、声明数不符) | 立即 `DEAD`,整包不落地 | 否 |
| `CODEC_ERROR` | 解码能力问题 | `FAILED` 退避 | 是 |
| `UNSUPPORTED` | 处理器或快照能力未实现 | `FAILED` 退避,受尝试上限约束 | 是 |
| `INFRA` | 基础设施或执行异常 | `FAILED` 退避 | 是 |
| `EXHAUSTED` | 尝试次数耗尽 | `DEAD``ERROR_CLASS` 被覆写为 `EXHAUSTED`(原始类别不保留,`LAST_ERROR` 留文本) | 是 |
回填放弃原因:`MISSING_ROW`(信箱行不存在,确定性结论)、`TRANSIENT_DEADLINE`(暂时性故障持续到 `R` 仍未打标)。两者都不写 `BACKFILL_AT`,都不等于标记已确认;`R` 之前不放弃。