chore(infra): 增加本地中间件编排、环境配置与 Kafka 降级支持

This commit is contained in:
windyboy
2026-09-07 15:11:06 +08:00
parent abacd6a3f4
commit dc68f1e1f8
5 changed files with 217 additions and 10 deletions
+27
View File
@@ -0,0 +1,27 @@
# =====================================================================
# msgexchange-v2 本地开发环境变量示例(ACM2-13 口径)
# 复制为 .env 或直接在本地启动时 export
# =====================================================================
# 1. 共享信箱 MySQLdev compose: mysql 服务)
MSGX_MAILBOX_URL=jdbc:mysql://localhost:3306/cdairport?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8mb4
MSGX_MAILBOX_USER=msgx_dev
MSGX_MAILBOX_PASSWORD=msgx_dev_pass
# 2. 自有 PostgreSQLdev compose: postgres 服务,Flyway V1.0.0 自动建表)
MSGX_PG_URL=jdbc:postgresql://localhost:5432/msgx
MSGX_PG_USER=msgx_dev
MSGX_PG_PASSWORD=msgx_dev_pass
# 3. Redis / Valkeydev compose: redis 服务,航班动态 + 快照 gen)
MSGX_REDIS_URI=redis://localhost:6379
# 4. Kafkadev compose: kafka 单节点 KRaft 服务,或对接现网/测试网)
MSGX_KAFKA_SERVERS=localhost:9092
# --- 旧版 Kafka Broker 兼容配置(如现网 0.10.x / 1.x 无 INIT_PRODUCER_ID 协议时启用)---
# 现代 Kafka3.x/4.x,如本地 compose):默认 acks=all, idempotence=true, max-in-flight=5
# 旧版 Kafka0.10.x/1.x):取消注释以下三行以触发兼容降级,防止 UnsupportedVersionException
# MSGX_KAFKA_ACKS=1
# MSGX_KAFKA_IDEMPOTENCE=false
# MSGX_KAFKA_MAX_IN_FLIGHT=1
+104
View File
@@ -0,0 +1,104 @@
# =====================================================================
# msgexchange-v2 本地开发依赖中间件栈(ACM2-13 口径)
# 兼容 Podman Compose 与 Docker Compose
# 包含:
# - mysql: 共享信箱 MySQL 8.4 LTS(库 cdairport,初始化 CMINMSGS/COUTMSGS
# - postgres: 自有 PostgreSQL 17-alpine(库 msgx,由应用 Flyway 建表)
# - redis: 航班动态 + 快照 gen 开源替代品 Valkey 8-alpine(兼容 Redis 7.2+ 协议与 Lua
# - kafka: 单节点 Apache Kafka 3.8.0 KRaft
# =====================================================================
services:
mysql:
image: mysql:8.4
container_name: msgx-dev-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: root_dev_pass
MYSQL_DATABASE: cdairport
MYSQL_USER: ${MSGX_MAILBOX_USER:-msgx_dev}
MYSQL_PASSWORD: ${MSGX_MAILBOX_PASSWORD:-msgx_dev_pass}
ports:
- "3306:3306"
volumes:
- ./deploy/dev/mysql-init:/docker-entrypoint-initdb.d:ro
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u$$MYSQL_USER -p$$MYSQL_PASSWORD --silent || exit 1"]
interval: 5s
timeout: 5s
retries: 10
start_period: 15s
postgres:
image: postgres:17-alpine
container_name: msgx-dev-postgres
restart: unless-stopped
environment:
POSTGRES_DB: msgx
POSTGRES_USER: ${MSGX_PG_USER:-msgx_dev}
POSTGRES_PASSWORD: ${MSGX_PG_PASSWORD:-msgx_dev_pass}
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB -h 127.0.0.1 || exit 1"]
interval: 5s
timeout: 5s
retries: 10
start_period: 5s
redis:
image: valkey/valkey:8-alpine
container_name: msgx-dev-redis
restart: unless-stopped
command: ["valkey-server", "--appendonly", "yes"]
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD-SHELL", "valkey-cli ping | grep PONG || exit 1"]
interval: 5s
timeout: 5s
retries: 10
start_period: 5s
kafka:
image: apache/kafka:3.8.0
container_name: msgx-dev-kafka
restart: unless-stopped
ports:
- "9092:9092"
environment:
# KRaft 单节点角色与集群 ID
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_CLUSTER_ID: "4L622nShTUiT8tCdRvgqgA"
# 监听器与协议映射
KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9093
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
# 单节点副本与分区配置(满足 acks=all + 幂等生产者)
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_DEFAULT_REPLICATION_FACTOR: 1
KAFKA_NUM_PARTITIONS: 1
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
KAFKA_LOG_DIRS: /tmp/kraft-combined-logs
healthcheck:
test: ["CMD-SHELL", "/opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --list || exit 1"]
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
volumes:
mysql_data:
pg_data:
redis_data:
+66
View File
@@ -0,0 +1,66 @@
-- =====================================================================
-- deploy/dev/mysql-init/01-mailbox.sql
-- 本地开发环境共享信箱 MySQL 初始化脚本(ACM2-13 / ACM2-12 口径)
--
-- 数据库:cdairport(他人系统库,本仓库生产不建表/不声明权威 schema;
-- 此处仅供本地 dev compose 容器初始化 CMINMSGS 与 COUTMSGS 供联调与轮询测试)。
-- 列定义与现役 legacy 实体(Cminmsg.java / Cmoutmsg.java)对齐。
-- =====================================================================
CREATE DATABASE IF NOT EXISTS `cdairport`
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
USE `cdairport`;
-- 入站信箱表(上游写报文原文,本系统 InboxPoller 1s 轮询读取并回填)
CREATE TABLE IF NOT EXISTS `CMINMSGS` (
`CMINMSGS_ID` BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增消息序号',
`CMINMSGS_CLOB_MSG` LONGTEXT NOT NULL COMMENT '原始 XML 报文内容',
`CMINMSGS_DATE_RECEIVED` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '信箱入库时间',
`CMINMSGS_DATE_PROCESSED` DATETIME DEFAULT NULL COMMENT '处理完成时间(NULL 表示未处理)',
`CMINMSGS_STATUS` VARCHAR(32) DEFAULT NULL COMMENT '处理状态(如 PROCESSED/ERROR',
`CMINMSGS_SUBSYSTEM_TYPE` VARCHAR(32) DEFAULT NULL COMMENT '子系统类型',
`CMINMSGS_SUBSYSTEM_SUBTYPE` VARCHAR(32) DEFAULT NULL COMMENT '子系统子类型',
`CMINMSGS_SUBSYSTEM_NAME` VARCHAR(64) DEFAULT NULL COMMENT '子系统名称',
`CMINMSGS_SUBSYSTEM_SEQUENCE` BIGINT DEFAULT NULL COMMENT '子系统序列号',
`CMINMSGS_SUBSYSTEM_DATE_SENT` DATETIME DEFAULT NULL COMMENT '子系统发送时间',
PRIMARY KEY (`CMINMSGS_ID`),
INDEX `idx_cminmsgs_poll` (`CMINMSGS_ID`, `CMINMSGS_DATE_PROCESSED`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='[DEV ONLY] 共享入站信箱表';
-- 历史归档表(ARCHIVE 任务将 1 天前的已处理信件归档至此)
CREATE TABLE IF NOT EXISTS `CMINMSGS_HST` (
`CMINMSGS_ID` BIGINT NOT NULL,
`CMINMSGS_CLOB_MSG` LONGTEXT NOT NULL,
`CMINMSGS_DATE_RECEIVED` DATETIME NOT NULL,
`CMINMSGS_DATE_PROCESSED` DATETIME DEFAULT NULL,
`CMINMSGS_STATUS` VARCHAR(32) DEFAULT NULL,
`CMINMSGS_SUBSYSTEM_TYPE` VARCHAR(32) DEFAULT NULL,
`CMINMSGS_SUBSYSTEM_SUBTYPE` VARCHAR(32) DEFAULT NULL,
`CMINMSGS_SUBSYSTEM_NAME` VARCHAR(64) DEFAULT NULL,
`CMINMSGS_SUBSYSTEM_SEQUENCE` BIGINT DEFAULT NULL,
`CMINMSGS_SUBSYSTEM_DATE_SENT` DATETIME DEFAULT NULL,
PRIMARY KEY (`CMINMSGS_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='[DEV ONLY] 共享入站信箱历史归档表';
-- 出站信箱表(本系统请求类或通知类报文写入,供他人读取发送)
CREATE TABLE IF NOT EXISTS `COUTMSGS` (
`COUTMSGS_ID` BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增出站序号',
`COUTMSGS_CLOB_MSG` LONGTEXT NOT NULL COMMENT '原始 XML 出站报文',
`COUTMSGS_DATE_INSERTED` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
`COUTMSGS_DATE_SENT` DATETIME DEFAULT NULL COMMENT '发送时间',
`ROUTINGID` VARCHAR(64) DEFAULT NULL COMMENT '路由标识(如 OSH5RQFD',
`COUTMSGS_ACK_REQD` VARCHAR(8) DEFAULT NULL COMMENT '是否需要 ACK',
`COUTMSGS_ACK_DATE_RECV` DATETIME DEFAULT NULL COMMENT '收到 ACK 时间',
`COUTMSGS_ACK_RESEND_TIMES` INT DEFAULT 0 COMMENT '重发次数',
`COUTMSGS_ERROR` VARCHAR(255) DEFAULT NULL COMMENT '错误信息',
`COUTMSGS_GROUP_ID` VARCHAR(64) DEFAULT NULL COMMENT '分组 ID',
`COUTMSGS_GROUP_ORDER` INT DEFAULT NULL COMMENT '组内顺序',
`COUTMSGS_NO_MESSAGES` INT DEFAULT NULL COMMENT '组内消息数',
`COUTMSGS_FINAL_GROUP_IND` VARCHAR(8) DEFAULT NULL COMMENT '最终组标记',
`COUTMSGS_TRUEFALS_GROUP` VARCHAR(8) DEFAULT NULL COMMENT '分组布尔标记',
`COUTMSGS_ENCRYPT` VARCHAR(8) DEFAULT NULL COMMENT '加密标记',
PRIMARY KEY (`COUTMSGS_ID`),
INDEX `idx_coutmsgs_sent` (`COUTMSGS_DATE_SENT`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='[DEV ONLY] 共享出站信箱表';
+14 -7
View File
@@ -18,17 +18,24 @@ eureka:
enabled: false enabled: false
# DB 仅在真实实装接入后需要;stub 模式不建连——datasources.default.enabled=false 经 # DB 仅在真实实装接入后需要;stub 模式不建连——datasources.default.enabled=false 经
# micronaut-jdbc 的 JdbcDataSourceEnabled 条件排除 DataSource bean"stub 不建连"落地) # micronaut-jdbc 的 JdbcDataSourceEnabled 条件排除 DataSource bean"stub 不建连"落地)
# 下方 url 仍保留合法默认(host/port/name 分拆,避免占位符默认值内嵌冒号解析坏) # 遵循 ACM2-12/ACM2-13 自有数据库(PostgreSQL)口径。真实接入时:设 MSGX_PG_URL + enabled=true
# 真实接入时:设 MSGX_DB_URL(或 MSGX_DB_HOST/PORT/NAME+ enabled=true。
datasources: datasources:
default: default:
enabled: false enabled: false
url: jdbc:mysql://${MSGX_DB_HOST:127.0.0.1}:${MSGX_DB_PORT:3306}/${MSGX_DB_NAME:msgexchange_dev} url: jdbc:postgresql://${MSGX_PG_HOST:127.0.0.1}:${MSGX_PG_PORT:5432}/${MSGX_PG_NAME:msgx}
username: ${MSGX_DB_USER:root} username: ${MSGX_PG_USER:msgx_dev}
password: ${MSGX_DB_PASSWORD:} password: ${MSGX_PG_PASSWORD:msgx_dev_pass}
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: org.postgresql.Driver
# 共享信箱 MySQL 适配配置(ACM2-12/ACM2-13):
mailbox:
shared-mysql:
enabled: false
url: jdbc:mysql://${MSGX_MAILBOX_HOST:127.0.0.1}:${MSGX_MAILBOX_PORT:3306}/${MSGX_MAILBOX_NAME:cdairport}?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8mb4
username: ${MSGX_MAILBOX_USER:msgx_dev}
password: ${MSGX_MAILBOX_PASSWORD:msgx_dev_pass}
driver-class-name: com.mysql.cj.jdbc.Driver
# stub 模式无 DataSourceFlyway 显式关闭(主配置默认 enabled:true 只作用于有 DataSource 的环境) # stub 模式无 DataSourceFlyway 显式关闭(主配置默认 enabled:true 只作用于有 DataSource 的环境)
flyway: flyway:
datasources: datasources:
+6 -3
View File
@@ -58,6 +58,7 @@ flyway:
# CminmsgMailbox/OutboxMailbox)随 U05 批次引入。 # CminmsgMailbox/OutboxMailbox)随 U05 批次引入。
mailbox: mailbox:
shared-mysql: shared-mysql:
enabled: false
url: ${MSGX_MAILBOX_URL} url: ${MSGX_MAILBOX_URL}
username: ${MSGX_MAILBOX_USER} username: ${MSGX_MAILBOX_USER}
password: ${MSGX_MAILBOX_PASSWORD} password: ${MSGX_MAILBOX_PASSWORD}
@@ -71,9 +72,11 @@ kafka:
servers: ${MSGX_KAFKA_SERVERS} servers: ${MSGX_KAFKA_SERVERS}
producers: producers:
default: # U03/R09Micronaut Kafka 按具名 producer 解析,须有 default 层 default: # U03/R09Micronaut Kafka 按具名 producer 解析,须有 default 层
acks: all # 默认 acks=all + 幂等(现代 Kafka 3.x+);若对接旧版 Broker(如现网 0.10.x/1.x,无 INIT_PRODUCER_ID 协议),
enable-idempotence: true # 经 MSGX_KAFKA_ACKS=1 与 MSGX_KAFKA_IDEMPOTENCE=false 降级兼容。
acks: ${MSGX_KAFKA_ACKS:all}
enable-idempotence: ${MSGX_KAFKA_IDEMPOTENCE:true}
max-in-flight-requests-per-connection: ${MSGX_KAFKA_MAX_IN_FLIGHT:5}
eureka: eureka:
client: client:
registration: registration: