feat: 新增中间件文档和内部通讯技能

新增中间件相关文档包括 RocketMQ、Nacos、PowerJob 的部署指南和故障分析文档,完善 Keepalived 和 MySQL 的文档内容。新增内部通讯技能模板和示例文件,包括 3P更新、公司通讯、FAQ回答等格式指南。优化服务文档结构,补充 FIX 引擎高可用架构说明。新增中间件综合指南,详细说明高可用部署方案和灾备转换原理。

新增 RocketMQ 5.3.2 集群部署文档,包含 Controller 模式详解和详细配置说明。新增 Nacos 和 PowerJob 部署文档,补充服务依赖和关键配置。更新 MySQL 故障分析文档,优化复制冲突解决流程。新增内部通讯技能模板文件,规范公司内部通讯格式。

docs: 补充服务文档和中间件 TODO 列表

新增 g3fo-exchange-fix-engine-service 服务文档,详细说明服务职责和关键配置。新增中间件 TODO 列表,跟踪待补充的文档内容。更新 Keepalived 部署文档,新增主库抢占前置检查脚本和配置说明。优化中间件文档结构,补充常见问题和性能优化建议。

style: 统一文档格式和代码块样式

统一所有文档的代码块格式和标题层级。优化表格显示样式,增强可读性。规范环境变量和配置项的显示方式。调整文档结构,确保逻辑清晰。修复部分拼写错误和格式问题。

chore: 新增 LICENSE 文件

新增内部通讯技能的 Apache 2.0 LICENSE 文件。补充文档版权信息。更新文件头部的元数据描述。规范文件命名和目录结构。
This commit is contained in:
2026-01-23 17:15:16 +08:00
parent 50455cc8c6
commit 3525aee49e
16 changed files with 2368 additions and 26 deletions
@@ -0,0 +1,44 @@
# 待添加的中间件文档
## 待添加中间件列表
以下中间件的文档尚未添加,需要后续补充:
### 1. RocketMQ
- [x] 部署文档 (deploy.md)
- [ ] 故障分析 (fault-analysis.md)
- [ ] 使用指南 (usage.md)
### 2. Nacos
- [x] 部署文档 (deploy.md)
- [ ] 故障分析 (fault-analysis.md)
- [ ] 使用指南 (usage.md)
### 3. Dufs
- [ ] 部署文档 (deploy.md)
- [ ] 故障分析 (fault-analysis.md)
- [ ] 使用指南 (usage.md)
### 4. PowerJob
- [x] 部署文档 (deploy.md)
- [ ] 故障分析 (fault-analysis.md)
- [ ] 使用指南 (usage.md)
## 已完成的中间件
- [x] Keepalived
- [x] deploy.md
- [x] fault-analysis.md
- [x] MySQL
- [x] deploy.md
- [x] fault-analysis.md
- [x] log-management.md
- [x] Redis
- [x] deploy.md
- [x] usage.md
@@ -138,6 +138,15 @@ vrrp_script check_mysql {
rise 2 # 连续 2 次成功判定为恢复
}
# 主库抢占前置检查(仅 Node A 需要)
vrrp_script check_preempt {
script "/etc/keepalived/check-preempt.sh"
interval 3 # 检测间隔:3 秒
weight -20 # 检测失败时,优先级扣 20(确保 A 低于 B)
fall 3
rise 2
}
vrrp_instance VI_1 {
state BACKUP # 所有节点统一设为 BACKUP,靠优先级决定 Master
interface ${INTERFACE} # 替换为宿主机实际网卡名(如 ens33/br0 等)
@@ -167,6 +176,7 @@ vrrp_instance VI_1 {
# 绑定检测脚本
track_script {
check_mysql
check_preempt
}
}
```
@@ -275,6 +285,41 @@ fi
chmod +x /data/keepalived/check-mysql.sh
```
### 3.5 主库抢占前置检查脚本(仅 Node A 需要)
当主库恢复后,希望仅在“副库端口正常 + 本地复制线程正常”时才允许抢占。若副库端口不通,则仍允许 30 秒后抢占。
路径:`/data/keepalived/check-preempt.sh`
如 Keepalived 以 Docker 方式运行,请在 Node A 的容器挂载中增加:
`/data/keepalived/check-preempt.sh:/etc/keepalived/check-preempt.sh:ro`
```bash
#!/bin/sh
# 逻辑说明:
# 1. 副库端口可达时,检查本地复制线程(IO/SQL)是否正常
# 2. 副库端口不可达时,直接放行抢占(避免无可用 DB)
PEER_IP=${NODE_B_IP}
if timeout 2 nc -z "${PEER_IP}" 3306 > /dev/null 2>&1; then
STATUS=$(docker exec -i mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "SHOW REPLICA STATUS\G" 2>/dev/null)
if echo "$STATUS" | grep -q "Replica_IO_Running: Yes" \
&& echo "$STATUS" | grep -q "Replica_SQL_Running: Yes"; then
exit 0
else
exit 1
fi
else
exit 0
fi
```
添加执行权限:
```bash
chmod +x /data/keepalived/check-preempt.sh
```
## 4. 启动与验证
### 4.1 启动容器
三台机器执行相同命令:
@@ -322,4 +367,5 @@ ip addr show ${INTERFACE} # 替换为实际网卡名
+ 所有节点 `virtual_router_id` 和认证信息必须一致;
+ 网卡名需替换为宿主机实际名称;
+ 仲裁节点 C 不配置 `virtual_ipaddress`,不挂载 MySQL 检测脚本。
+ 若使用 `check_preempt`,`weight` 需确保 A 检测失败时优先级低于 B(例如 A=110,B=100,weight=-20 → A=90)。
@@ -23,3 +23,4 @@
| 15 | C Keepalived 停机 | 正常/正常 | 正常/正常 | 故障(离线) | A=110、B=100、C=离线 | Node A | C 仅为仲裁,离线不影响 A/B 选举 |
| 16 | A、B MySQL 均停机 + C 停机 | 故障/正常 | 故障/正常 | 故障(离线) | A=60、B=50、C=离线 | Node A | C 离线不影响 A/B 选举 |
| 17 | 所有节点 Keepalived 均停机 | 正常/故障(离线) | 正常/故障(离线) | 故障(离线) | 全离线 | 无节点绑定 VIP | 无 Keepalived 参与选举,VIP 失联 |
| 18 | A 恢复但复制异常(check_preempt 失败) | 恢复/正常 | 正常/正常 | 正常 | A=90、B=100、C=40 | Node B | 副库端口正常但 A 本地复制异常,A 降权不抢占 |
@@ -0,0 +1,373 @@
# 中间件高可用部署综合指南
## 1. 文档概述
本指南基于两台高性能服务器加一台低配置服务器的组合方案,详细介绍各中间件的核心功能、高可用部署方案以及灾备转换的基本原理。所有中间件均采用容器化部署,确保部署一致性和可维护性。
## 2. 部署架构总览
### 2.1 节点配置
| 节点类型 | 数量 | 配置 | 角色分配 |
| ------------ | ---- | --------------------- | ------------------------------------ |
| 高性能服务器 | 2 | CPU/内存/存储配置较高 | 核心业务处理节点,部署所有中间件服务 |
| 低配置服务器 | 1 | CPU/内存/存储配置较低 | 仅参与选举和监控,不部署核心业务服务 |
### 2.2 整体架构图
```mermaid
graph TB
%% 机器 A
subgraph Srv_A [高性能服务器 A: .230]
direction TB
KA[Keepalived M]
AppA[业务应用集群]
subgraph MW_A [中间件/数据库]
MA[(MySQL M1)]
RA[Redis Master]
RMA[RocketMQ Broker M]
end
subgraph Cluster_Comp_A [集群仲裁/管理 A]
RS1[Redis Sentinel 1]
RNC1[RMQ NS/Controller 1]
NA[Nacos/PowerJob]
end
end
%% 机器 B
subgraph Srv_B [高性能服务器 B: .200]
direction TB
KB[Keepalived B]
AppB[业务应用集群]
subgraph MW_B [中间件/数据库]
MB[(MySQL M2)]
RB[Redis Slave]
RMB[RocketMQ Broker S]
end
subgraph Cluster_Comp_B [集群仲裁/管理 B]
RS2[Redis Sentinel 2]
RNC2[RMQ NS/Controller 2]
NB[Nacos/PowerJob]
end
end
%% 机器 C
subgraph Srv_C [仲裁服务器 C: .110]
KC[Keepalived Arbiter]
RS3[Redis Sentinel 3]
RNC3[RMQ NS/Controller 3]
end
%% VIP 逻辑
VIP((Virtual IP: .233))
KA -.->|管理| VIP
KB -.->|管理| VIP
%% 核心访问流
AppA & AppB ==> VIP
VIP ==> MA & MB
%% 跨机数据同步
MA <==>|双主复制| MB
RA --->|主从同步| RB
RMA <==>|同步| RMB
NA <==>|同步| NB
%% 集群内部协调 (逻辑表示)
RS1 --- RS2 --- RS3
RNC1 --- RNC2 --- RNC3
%% 监控选主关系 (虚线)
RS1 & RS2 & RS3 -.->|监控/选主| RA & RB
RNC1 & RNC2 & RNC3 -.->|路由/选主| RMA & RMB
%% 样式
classDef server fill:#f0f5ff,stroke:#2f54eb;
classDef arbiter fill:#fff1f0,stroke:#ff4d4f;
classDef vip fill:#f6ffed,stroke:#52c41a,stroke-width:2px;
class Srv_A,Srv_B server;
class Srv_C arbiter;
class VIP vip;
```
## 3. 中间件详细说明
### 3.1 Keepalived
#### 3.1.1 核心功能
- 实现VIP(虚拟IP)的高可用管理
- 自动故障检测和VIP切换
- 防止脑裂问题
#### 3.1.2 高可用部署方案
- **部署模式**:三节点集群(2台高性能服务器+1台低配置服务器)
- **角色分配**:
- 高性能服务器A:Master节点(基础优先级110)
- 高性能服务器B:Backup节点(基础优先级100)
- 低配置服务器C:Arbiter节点(基础优先级40,仅参与选举)
- **核心配置**:
- VIP:192.168.3.233
- 采用单播通信方式
- 集成MySQL健康检查脚本
#### 3.1.3 灾备转换原理
- **优先级规则**:VIP归属由有效优先级决定,基础优先级A > B > C
- **故障检测**:通过脚本检测MySQL端口,故障时优先级扣减50
- **脑裂防护**:Arbiter节点确保至少2/3节点正常才能进行VIP切换
- **切换流程**:
1. 检测到Master节点故障
2. Backup节点发起选举
3. 获得Arbiter节点支持后成为新Master
4. 绑定VIP并提供服务
### 3.2 MySQL
#### 3.2.1 核心功能
- 关系型数据库服务
- 数据持久化存储
- 双主双向复制
#### 3.2.2 高可用部署方案
- **部署模式**:双主(Source-Source)复制集群
- **节点分配**:仅部署在2台高性能服务器上
- **核心配置**:
- GTID + AUTO_POSITION:自动定位同步位点
- ROW模式binlog:保证复制一致性
- 自增键隔离:A节点生成奇数主键,B节点生成偶数主键
- 持久化配置:innodb_flush_log_at_trx_commit=1,sync_binlog=1
#### 3.2.3 灾备转换原理
- **双主同步**:两台节点互为主从,实时同步数据
- **故障检测**:通过Keepalived的健康检查脚本检测MySQL端口
- **切换流程**:
1. Keepalived检测到MySQL故障
2. 降低对应节点优先级
3. VIP自动切换到健康节点
4. 应用通过VIP继续访问MySQL服务
### 3.3 Redis
#### 3.3.1 核心功能
- 分布式缓存服务
- 数据持久化存储
- 高可用故障转移
#### 3.3.2 高可用部署方案
- **部署模式**:Redis Sentinel集群
- **节点分配**:
- 2台高性能服务器:部署Redis主从节点
- 3台服务器:均部署Sentinel节点
- **核心配置**:
- 主从复制:1主1从
- Sentinel集群:3节点,quorum=2
- 持久化:AOF + RDB混合模式
- 密码认证:统一密码管理
#### 3.3.3 灾备转换原理
- **健康检测**:Sentinel节点定期检查Redis主从状态
- **故障判定**:当quorum个Sentinel节点判定主节点故障时触发故障转移
- **切换流程**:
1. Sentinel集群选举Leader
2. Leader选择最优Slave节点
3. 将Slave提升为新Master
4. 配置其他Slave指向新Master
5. 通知客户端更新主节点信息
### 3.4 Nacos
#### 3.4.1 核心功能
- 服务注册与发现
- 配置中心
- Dubbo注册中心
#### 3.4.2 高可用部署方案
- **部署模式**:集群部署
- **节点分配**:部署在2台高性能服务器上,配置1个虚拟节点
- **核心配置**:
- 数据库存储:MySQL持久化元数据
- 集群规模:3节点(2实际+1虚拟)
- 数据同步:基于数据库的共享存储
#### 3.4.3 灾备转换原理
- **无状态设计**:所有节点共享同一MySQL数据库
- **故障恢复**:节点故障后,其他节点自动接管服务
- **客户端容错**:客户端配置多个Nacos地址,自动切换
### 3.5 PowerJob
#### 3.5.1 核心功能
- 分布式任务调度
- 多样化任务类型支持
- 任务管理与监控
#### 3.5.2 高可用部署方案
- **部署模式**:集群部署
- **节点分配**:部署在2台高性能服务器上
- **核心配置**:
- 数据库存储:MySQL持久化任务信息
- 集群通信:基于Akka实现节点间通信
- 负载均衡:任务自动分配到可用节点
#### 3.5.3 灾备转换原理
- **无状态设计**:所有节点共享同一MySQL数据库
- **任务容错**:节点故障时,任务自动转移到其他节点执行
- **客户端配置**:Worker节点配置多个Server地址,自动切换
### 3.6 RocketMQ
#### 3.6.1 核心功能
- 分布式消息中间件
- 高吞吐、高可用
- 支持事务消息、延时消息
- 自动主从切换
#### 3.6.2 高可用部署方案
- **部署模式**:Controller模式集群
- **节点分配**:
- 3台服务器:均部署NameServer和Controller
- 2台高性能服务器:部署Broker(1主1从)
- **核心配置**:
- Controller集群:基于jRaft实现,3节点
- Broker配置:ASYNC_MASTER + SLAVE
- 持久化:异步刷盘
#### 3.6.3 灾备转换原理
- **Controller集群**:基于Raft协议选举Leader,管理Broker元数据
- **自动主从切换**:
1. Controller监控Master Broker状态
2. 检测到故障后,选举最优Slave
3. 将Slave提升为新Master
4. 更新NameServer中的路由信息
5. 客户端自动获取新的Master地址
## 4. 灾备转换流程
### 4.1 单节点故障场景
```mermaid
graph TB
%% 故障离线节点 (服务器 A)
subgraph Srv_A [高性能服务器 A: .230 <br/> 🔴 全机离线]
direction TB
KA[Keepalived - 离线]
AppA[业务应用 - 离线]
subgraph MW_A [中间件/数据库]
MA[(MySQL - 离线)]
RA[Redis - 离线]
RMA[RMQ Broker - 离线]
end
end
%% 故障转移后的活动节点 (服务器 B)
subgraph Srv_B [高性能服务器 B: .200 <br/> 🟢 承载全量业务]
direction TB
KB[Keepalived - Master]
AppB[业务应用 - 正常]
subgraph MW_B [中间件/数据库]
MB[(MySQL - Master)]
RB[Redis - NEW Master]
RMB[RMQ Broker - NEW Master]
end
subgraph Cluster_B [管理节点]
NB[Nacos/PowerJob]
RNCB[RMQ NS/Controller]
end
end
%% 仲裁节点 (服务器 C)
subgraph Srv_C [仲裁服务器 C: .110]
KC[Keepalived Arbiter]
RS[Redis Sentinel 集群]
RNCC[RMQ NS/Controller]
end
%% VIP 与流量重定向
VIP((Virtual IP: .233))
KB ==>|接管| VIP
AppB ==>|内部访问| VIP
VIP ==>|读写| MB
%% 故障转移逻辑 (核心连线)
RS -.->|1.检测到故障| RA
RS ==>|2.提升为主| RB
RNCC -.->|1.检测到故障| RMA
RNCC ==>|2.提升为主| RMB
%% 样式定义
classDef offline fill:#f5f5f5,stroke:#d9d9d9,stroke-dasharray: 5 5,color:#bfbfbf;
classDef active fill:#e6f7ff,stroke:#1890ff,stroke-width:2px;
classDef arbiter fill:#fff1f0,stroke:#ff4d4f;
classDef highlight fill:#f6ffed,stroke:#52c41a,stroke-width:2px;
class Srv_A,KA,AppA,MA,RA,RMA offline;
class Srv_B,KB,AppB,MB,RB,RMB,NB,RNCB active;
class Srv_C,KC,RS,RNCC arbiter;
class VIP highlight;
```
### 4.2 灾备转换步骤
1. **故障检测**:各中间件自身的健康检查机制或外部监控系统检测到节点故障
2. **优先级调整**:Keepalived根据健康状态调整节点优先级
3. **VIP切换**:Keepalived将VIP绑定到优先级最高的健康节点
4. **服务接管**:
- Redis:Sentinel选举新Master
- RocketMQ:Controller自动将Slave提升为Master
- MySQL:应用通过VIP访问健康节点
- Nacos/PowerJob:健康节点自动接管服务
5. **客户端切换**:客户端通过配置的多节点地址自动连接到健康节点
## 5. 监控与维护
### 5.1 监控指标
| 中间件 | 核心监控指标 |
| ---------- | ------------------------------------------ |
| Keepalived | VIP状态、节点优先级、健康检查结果 |
| MySQL | 主从复制状态、连接数、查询响应时间、慢查询 |
| Redis | 主从状态、内存使用率、命中率、连接数 |
| Nacos | 服务注册数量、配置更新次数、节点状态 |
| PowerJob | 任务执行成功率、任务堆积量、节点状态 |
| RocketMQ | 消息堆积量、发送/消费TPS、Broker状态 |
### 5.2 维护建议
1. **定期备份**:定期备份数据库、配置文件和重要数据
2. **日志管理**:配置日志轮转,定期清理过期日志
3. **安全加固**:
- 开启访问认证
- 配置防火墙规则
- 定期更新密码
4. **性能优化**:
- 根据负载调整资源配置
- 优化中间件参数
- 定期进行性能测试
5. **灾备演练**:定期进行故障模拟演练,验证灾备转换流程
## 6. 总结
本指南基于两台高性能服务器加一台低配置服务器的组合方案,详细介绍了各中间件的高可用部署方案和灾备转换原理。通过合理的角色分配和架构设计,实现了资源的优化利用和系统的高可用性。
各中间件均采用容器化部署,通过Keepalived实现VIP的统一管理,确保了系统在节点故障时能够自动进行灾备转换,保障业务的连续性和可用性。
建议在实际部署过程中,根据业务需求和资源情况,对各中间件的配置进行适当调整和优化,以达到最佳的性能和可用性。
@@ -4,24 +4,49 @@
> 1. **强制参数**: 所有 `docker exec` 命令必须包含 `-h127.0.0.1` 参数。
> 2. **双重输出**: 涉及 SQL 操作时,必须同时输出 `Docker 执行命令` 和 `纯 SQL 脚本`。
> 3. **默认连接**: 默认使用 `-uroot -pafe123456 -h127.0.0.1`。
> 4. **排障连贯性**: 诊断复制冲突时,在提供 **A. 查看复制状态概要** 后,**必须紧跟** 提供 **B. 自动提取错误详情** 脚本,以便用户直接获取修复建议。
## 1. 复制冲突解决(主键/唯一键重复)
## 1. 复制冲突解决(主键/唯一键重复或记录缺失)
### 1.1 快速定位冲突信息
提取冲突 GTID、表、值(直接执行,自动解析错误日志):
当复制中断时,**必须按顺序执行以下两步**:首先查看概要,然后提取详细错误以获取修复脚本。
**A. 查看复制状态概要:**
```bash
# 方式 1: 传统状态查看 (重点关注 Last_SQL_Error)
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "SHOW REPLICA STATUS\G" | grep -E "Replica_.*_Running|Last_SQL_Error|Retrieved_Gtid_Set|Executed_Gtid_Set"
# 方式 2: 多线程环境下查看详情 (若启用并行复制,SHOW REPLICA STATUS 只能看到协调线程错误)
docker exec -it mysql mysql -uroot -pafe123456 -h127.0.0.1 -e "SELECT * FROM performance_schema.replication_applier_status_by_worker WHERE LAST_ERROR_NUMBER > 0\G"
```
**B. 自动提取错误详情(支持 1062 重复键 / 1032 记录未找到):**
直接在宿主机执行以下脚本,它会自动解析错误日志并生成对应的修复方案:
```bash
grep "Duplicate entry" /data/mysql/logs/mysql_error.log | perl -nle '
if (/^(\S+).*?transaction\s+'\''([^'\'']+)'\''.*?table\s+([^\s;]+);.*?Duplicate entry\s+'\''([^'\'']+)'\''\s+for\s+key\s+'\''([^'\'']+)'\''/) {
print "\n" . "="x50;
print "时间: $1";
print "GTID: $2";
print "表名: $3";
print "冲突值: $4 (索引: $5)";
print "\n方案 A (删除冲突行):";
print "DELETE FROM $3 WHERE [主键列] = \x27$4\x27;";
print "\n方案 B (跳过此事务):";
print "STOP REPLICA; SET GTID_NEXT=\x27$2\x27; BEGIN; COMMIT; SET GTID_NEXT=\x27AUTOMATIC\x27; START REPLICA;";
# 提取冲突 GTID、表、冲突值及修复建议
grep -aE "Duplicate entry|Error_code: 1032" /data/mysql/logs/mysql_error.log | perl -nle '
if (/^(\S+).*?transaction\s+[\x27"]([^\x27"]+)[\x27"].*?table\s+([^\s;]+);/) {
my ($time, $gtid, $table) = ($1, $2, $3);
print "\n" . "="x60;
print "时间: $time";
print "GTID: $gtid";
print "表名: $table";
if (/Duplicate entry\s+[\x27"]([^\x27"]+)[\x27"]\s+for\s+key\s+[\x27"]([^\x27"]+)[\x27"]/) {
print "类型: 1062 (主键/唯一键重复)";
print "冲突值: $1 (索引: $2)";
print "\n方案 A (手动修复 - 删除从库冲突行):";
print "DELETE FROM $table WHERE [主键列] = \x27$1\x27;";
print "\n方案 B (跳过事务 - 保持从库现状):";
print "STOP REPLICA; SET GTID_NEXT=\x27$gtid\x27; BEGIN; COMMIT; SET GTID_NEXT=\x27AUTOMATIC\x27; START REPLICA;";
} elsif (/Error_code: 1032|HA_ERR_KEY_NOT_FOUND/) {
print "类型: 1032 (记录未找到 - 通常是 Delete/Update 目标不存在)";
print "说明: 目标行在从库已不存在,Delete 操作已实质生效。";
print "\n方案 A (直接跳过 - 安全):";
print "STOP REPLICA; SET GTID_NEXT=\x27$gtid\x27; BEGIN; COMMIT; SET GTID_NEXT=\x27AUTOMATIC\x27; START REPLICA;";
}
}
'
```
@@ -0,0 +1,201 @@
# Nacos 部署配置
## Nacos 用途说明
Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。在项目中,Nacos 主要用于以下场景:
### 1. 注册中心
- **服务注册**:所有微服务实例启动时会自动向 Nacos 注册自己的信息,包括服务名称、IP 地址、端口号等
- **服务健康检查**:Nacos 会定期检查注册的服务实例是否健康,自动剔除不健康的实例
- **高可用设计**:通过集群部署确保注册中心的可用性,避免单点故障
### 2. 服务发现
- **服务消费者查找服务**:服务消费者通过 Nacos 获取所需服务的可用实例列表
- **负载均衡**:提供服务实例的负载均衡策略,支持权重配置
- **实时更新**:服务实例变化时,Nacos 会实时通知消费者,确保服务列表的准确性
### 3. Dubbo 注册中心
- **Dubbo 服务注册**:Dubbo 服务提供者将服务注册到 Nacos
- **Dubbo 服务发现**:Dubbo 服务消费者从 Nacos 获取服务列表
- **元数据管理**:Dubbo 服务的元数据信息(如接口定义、方法签名等)存储在 Nacos 中
### 4. 配置中心
- **集中式配置管理**:所有服务的配置集中存储在 Nacos 中,避免配置分散在各个服务中
- **动态配置更新**:支持配置的动态修改,无需重启服务即可生效
- **配置版本管理**:记录配置的历史版本,支持回滚操作
- **配置分组与命名空间**:支持按环境、应用等维度管理配置
## Docker Compose 配置
```yaml
nacos:
image: nacos-registry.cn-hangzhou.cr.aliyuncs.com/nacos/nacos-server:v3.1.1
container_name: nacos
restart: always
depends_on:
- mysql
deploy:
resources:
limits:
memory: 2G
replicas: 1
placement:
constraints:
- node.role == manager
ports:
- 8848:8848
- 8849:8080
- 9848:9848
- 9849:9849
- 7848:7848
- 6848:9080
volumes:
- /etc/localtime:/etc/localtime
- /etc/timezone:/etc/timezone
- /data/nacos/conf/application.properties:/home/nacos/conf/application.properties
- /data/nacos/conf/cluster.conf:/home/nacos/conf/cluster.conf
- /data/nacos/data:/home/nacos/data
- /data/nacos/logs:/home/nacos/logs
- /data/nacos/lib:/home/nacos/lib
environment:
- JAVA_OPT=-javaagent:/home/nacos/lib/jasypt-agent.jar
- TZ=Asia/Hong_Kong
- SPRING_DATASOURCE_PLATFORM=mysql
- MODE=cluster
- NACOS_AUTH_TOKEN=LldB9CGYrmmbhIQOIFlg3L3avFB1wbUw8s1E0lL6WZc=
- NACOS_AUTH_IDENTITY_KEY=G3SF
- NACOS_AUTH_IDENTITY_VALUE=afe123456
- NACOS_SERVERS=192.168.3.230:8848 192.168.3.200:8848 192.168.4.250:8848
```
## 集群配置文件 (`/data/nacos/conf/cluster.conf`)
```
#2025-12-29T09:21:31.265596226
192.168.3.200:8848
192.168.3.230:8848
192.168.4.250:8848
```
## 应用配置文件 (`/data/nacos/conf/application.properties`)
```properties
nacos.server.main.port=8848
nacos.inetutils.prefer-hostname-over-ip=false
### Specify local server's IP:
nacos.inetutils.ip-address=192.168.3.230
spring.sql.init.platform=mysql
### Count of DB:
db.num=1
db.url.0=jdbc:mysql://192.168.3.233:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=afe123456
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
nacos.config.push.maxRetryTime=50
nacos.naming.empty-service.auto-clean=true
nacos.naming.empty-service.clean.initial-delay-ms=50000
nacos.naming.empty-service.clean.period-time-ms=30000
nacos.ai.mcp.registry.port=9080
nacos.server.contextPath=/nacos
server.tomcat.accesslog.enabled=true
### accesslog automatic cleaning time
server.tomcat.accesslog.max-days=30
### The access log pattern:
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
server.tomcat.basedir=file:.
#*************** API Related Configurations ***************#
### Include message field
server.error.include-message=ALWAYS
#*************** Nacos Console Related Configurations ***************#
### Nacos Console Main port
nacos.console.port=8080
### Nacos Server Web context path:
nacos.console.contextPath=
### Nacos Server context path, which link to nacos server `nacos.server.contextPath`, works when deployment type is `console`
nacos.console.remote.server.context-path=/nacos
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
### The auth system to use, default 'nacos' and 'ldap' is supported, other type should be implemented by yourself:
nacos.core.auth.system.type=nacos
### If turn on auth system:
# Whether open nacos server API auth system
nacos.core.auth.enabled=false
# Whether open nacos admin API auth system
nacos.core.auth.admin.enabled=false
# Whether open nacos console API auth system
nacos.core.auth.console.enabled=false
### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay.
nacos.core.auth.caching.enabled=true
nacos.core.auth.server.identity.key=
nacos.core.auth.server.identity.value=
nacos.core.auth.plugin.nacos.token.cache.enable=false
nacos.core.auth.plugin.nacos.token.expire.seconds=18000
### The default token (Base64 string):
#nacos.core.auth.plugin.nacos.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=
nacos.core.auth.plugin.nacos.token.secret.key=
nacos.istio.mcp.server.enabled=false
nacos.k8s.sync.enabled=false
nacos.deployment.type=merged
```
## Spring Boot 配置连接集群
### Spring Cloud 配置
```yaml
spring:
cloud:
nacos:
# 注册中心
discovery:
enabled: true
server-addr: 192.168.3.200:8848,192.168.3.230:8848
service: ${app.service-name}-app
namespace: dev
group: app-server
```
### Dubbo 配置
```yaml
# Dubbo配置
dubbo:
registry:
address: nacos://192.168.3.230:8848,192.168.3.200:8848
metadata-report:
address: nacos://192.168.3.230:8848,192.168.3.200:8848
```
## 部署说明
1. **当前部署情况**:
- 实际部署了两台主机:`192.168.3.200` 和 `192.168.3.230`
- `192.168.4.250` 是虚拟节点,用于解决集群节点显示问题
2. **集群显示问题**:
- 配置3个节点(实际2个+1个虚拟)可以解决节点状态显示异常问题
- 当只配置2个实际节点时,会出现节点互相看不到的情况
- 添加虚拟节点后,实际节点可以正常显示在线状态
3. **数据同步**:
- 配置3个节点后,数据可以在实际节点间正常同步
- 在任一实际节点修改配置,其他实际节点可以获取到最新数据
4. **注意事项**:
- 确保MySQL数据库已正确配置并可访问
- 调整 `nacos.inetutils.ip-address` 为当前服务器的实际IP
- 根据实际部署环境调整 volumes 映射路径
- 监控Nacos集群状态,确保至少两个实际节点正常运行
@@ -0,0 +1,173 @@
# PowerJob 部署配置
## PowerJob 用途说明
PowerJob 是一个分布式任务调度与计算框架,专注于解决大规模任务调度问题,提供丰富的任务类型和强大的调度能力。在项目中,PowerJob 主要用于以下场景:
### 1. 分布式任务调度
- **定时任务调度**:支持 cron 表达式、固定延迟、固定频率等多种调度方式
- **任务分片**:将大任务拆分为多个小任务,并行执行,提高处理效率
- **任务依赖**:支持任务间的依赖关系配置,实现复杂的工作流
- **高可用设计**:通过集群部署确保任务调度的可靠性,避免单点故障
### 2. 多样化任务类型
- **HTTP 任务**:直接调用 HTTP 接口执行任务
- **Java 任务**:执行 Java 代码,支持动态加载和执行
- **Shell 任务**:执行 Shell 脚本
- **Python 任务**:执行 Python 脚本
- **MapReduce 任务**:支持大数据处理场景
### 3. 任务管理与监控
- **可视化管理界面**:提供 Web 控制台,方便查看和管理任务
- **实时监控**:实时监控任务执行状态、日志和结果
- **告警机制**:支持任务失败、超时等告警通知
- **历史记录**:保存任务执行历史,便于追溯和分析
## Docker Compose 配置
```yaml
powerjob-server:
image: powerjob/powerjob-server:v5.1.2
container_name: powerjob-server
restart: always
depends_on:
- mysql
deploy:
resources:
limits:
memory: 1536M
replicas: 1
placement:
constraints:
- node.role == manager
networks:
- my-net
ports:
- 7700:7700
- 10086:10086
- 10010:10010
- 10077:10077
volumes:
- /etc/localtime:/etc/localtime
- /etc/timezone:/etc/timezone
- /data/powerjob/data:/root/powerjob/server
- /data/powerjob/application.properties:/application.properties
- /data/powerjob/lib:/app/lib
environment:
- JVMOPTIONS=-Dpowerjob.network.external.address=192.168.3.230 -Dpowerjob.network.local.address=0.0.0.0 -javaagent:/app/lib/jasypt-agent.jar
```
## 应用配置文件 (`/data/powerjob/application.properties`)
```properties
spring.datasource.core.jdbc-url=jdbc:mysql://192.168.3.233:3306/powerjob?useUnicode=true&characterEncoding=UTF-8
spring.datasource.core.username=root
spring.datasource.core.password=ENC(RjBbbZtMkQ1XoESFu6Wo7XeC29GcDkeIiIq92ONWx2odVz9NAmClnxjRXJwq1dNI)
#spring.datasource.core.password=afe123456
jasypt.encryptor.password=1234
#jasypt.encryptor.algorithm=PBEWITHHMACSHA512ANDAES_256
#jasypt.encryptor.iv-generator-classname=org.jasypt.iv.RandomIvGenerator
oms.mongodb.enable=false
spring.profiles.active=product
```
## Spring Boot 配置连接集群
```yaml
powerjob:
worker:
app-name: ${app.service-name}
protocol: http
server-address: 192.168.3.230:7700,192.168.3.200:7700
```
## 部署说明
### 1. 端口说明
| 端口 | 作用 | 说明 |
|------|------|------|
| 7700 | PowerJob 服务器的 Web 服务端口 | 用于访问 Web 控制台,接收 Worker 注册和任务请求,必须打开 |
| 10086 | Akka 端口 | PowerJob 配置的 Akka 端口,用于内部通信 |
| 10010 | 多语言客户端 HTTP 端口 | PowerJob 配置的多语言客户端 HTTP 端口 |
| 10077 | MU 协议端口 | PowerJob 配置的 MU 协议端口,可选打开 |
### 端口配置原则
1. **最省事的方法**:所有端口(7700 + 10086 + 10010 + 10077)全打开
2. **精细化控制原则**:
- 对于任何用户,7700 端口必须打开,这是调度服务器的 Web 服务端口
- `oms.协议.port` 的端口按需打开,考虑 server-server 和 server-worker 通讯场景:
- server-server 默认通过 HTTP 协议交互(由 `oms.transporter.main.protocol` 控制),必须打开 HTTP 10010 端口
- server-worker 部分通过 HTTP,部分通过 AKKA,需要打开 AKKA 的 10086 端口
### 主要配置项说明
| 配置项 | 含义 | 是否必填 |
|--------|------|----------|
| server.port | SpringBoot 配置,HTTP 端口号,默认 7700 | 否,且不建议更改 |
| oms.transporter.active.protocols | server 需要激活的通讯协议,建议激活全部支持的协议 | 否,且不建议更改 |
| oms.transporter.main.protocol | 主要通讯协议,用于 server 与 server 之间的通讯 | 否 |
| oms.akka.port | PowerJob 配置,Akka 端口号,默认 10086 | 否,且不建议更改 |
| oms.http.port | PowerJob 配置,多语言客户端 HTTP 端口号,默认 10010 | 否,且不建议更改 |
| oms.mu.port | PowerJob 配置,MU 协议端口号,默认 10077 | 是 |
| oms.table-prefix | 自定义数据库表名前缀 | 是 |
| spring.datasource.core.xxx | 关系型数据库连接配置 | 否 |
| spring.mail.xxx | 邮件配置 | 是,未配置情况下将无法使用邮件报警功能 |
| oms.container.retention.local | 本地容器保留天数,负数代表永久保留 | 是 |
| oms.container.retention.remote | 远程容器保留天数,负数代表永久保留 | 是 |
| oms.instanceinfo.retention | 任务实例和工作流实例信息的保留天数 | 是,推荐使用默认配置,生产环境保留 7 天 |
| oms.auth.initiliaze.admin.password | 系统初始化时默认创建的超级管理员密码 | 是,默认值 powerjob_admin,无此配置时,随机生成密码 |
| oms.auth.dingtalk.* | 钉钉用户账号体系相关配置内容 | 否,仅启用钉钉账号登录体系时需要配置 |
### 2. 目录准备
在部署 PowerJob 之前,需要创建以下目录:
```bash
mkdir -p /data/powerjob/{data,lib}
```
### 3. 环境变量说明
- **JVMOPTIONS**:
- `-Dpowerjob.network.external.address`:PowerJob 服务器的外部访问地址,用于 Worker 连接
- `-Dpowerjob.network.local.address`:PowerJob 服务器的本地绑定地址
- `-javaagent:/app/lib/jasypt-agent.jar`:Jasypt 加密代理,用于解密配置文件中的敏感信息
### 4. 配置文件说明
- **spring.datasource.core.jdbc-url**:MySQL 数据库连接 URL
- **spring.datasource.core.username**:MySQL 数据库用户名
- **spring.datasource.core.password**:MySQL 数据库密码(支持 Jasypt 加密)
- **jasypt.encryptor.password**:Jasypt 加密密钥
- **oms.mongodb.enable**:是否启用 MongoDB(用于存储任务日志,默认 false)
- **spring.profiles.active**:Spring Boot 激活的配置文件
### 5. 注意事项
1. **数据库配置**:
- 确保 MySQL 数据库已创建,并且用户具有足够的权限
- 首次启动时,PowerJob 会自动创建所需的表结构
2. **集群部署**:
- 可以部署多个 PowerJob 服务器实例,通过负载均衡提高可用性
- 所有实例共享同一个 MySQL 数据库
- Worker 配置中指定多个服务器地址,实现高可用连接
3. **安全配置**:
- 生产环境中建议使用 Jasypt 加密数据库密码等敏感信息
- 调整 Jasypt 加密密钥,避免使用默认密钥
4. **资源限制**:
- 根据实际任务量调整内存限制(当前配置为 1536M)
- 监控服务器资源使用情况,及时调整配置
## 相关文档
- [PowerJob 官方文档](https://www.yuque.com/powerjob/guidence/deploy_server)
- [PowerJob GitHub 仓库](https://github.com/PowerJob/PowerJob)
@@ -0,0 +1,961 @@
# RocketMQ 5.3.2 集群部署文档
## 一、概述
### 1.1 核心功能
RocketMQ 是一款分布式消息中间件,具有高吞吐、高可用、支持事务消息、延时消息等特性。RocketMQ 5.x 引入了 Controller 模式,实现了自动主从切换,提升了集群的高可用能力。
### 1.2 Controller 模式说明
RocketMQ 5.x 引入了基于 jRaft 的 Controller 模式,实现了以下核心功能:
- **自动主从切换**:当 Master 节点故障时,Controller 自动选举新的 Master,无需人工干预
- **元数据管理**:统一管理 Topic、订阅组等元数据,避免元数据不一致
- **负载均衡**:自动进行 Broker 负载均衡,优化集群资源利用率
### 1.3 适用场景
- 生产环境下的高可用消息队列需求
- 需要事务消息、延时消息的分布式系统
- 大规模消息吞吐场景(百万级 TPS)
### 1.4 前置条件
- **运行环境**:Docker & Docker Compose
- **镜像版本**:apache/rocketmq:5.3.2
- **网络规划**:所有节点需网络互通,且需明确各宿主机的外部 IP
- **集群规模**:建议至少 3 个节点组成集群(NameServer、Broker、Controller 各 3 个实例)
---
## 二、环境准备
### 2.1 节点信息规划
| 节点 | 主机IP | brokerId | jRaftServerId | 机器配置 | 角色 |
| :---- | :------------ | :------- | :----------------- | :------- | :-------------------------------- |
| 节点1 | 192.168.3.230 | 0 | 192.168.3.230:9880 | 高性能 | Master + NameServer + Controller |
| 节点2 | 192.168.3.200 | 1 | 192.168.3.200:9880 | 高性能 | Slave + NameServer + Controller |
| 节点3 | 192.168.3.110 | - | 192.168.3.110:9880 | 低配 | NameServer + Controller(仅选举) |
**架构说明**:
- **3台机均部署 NameServer**:NameServer 作为服务注册发现中心,所有节点都需要部署以避免单点
- **2台高性能机部署 Broker**:Broker 负责消息存储和转发,对性能要求高,仅在两台高性能机上部署
- **Controller 内嵌于 NameServer**:Controller 基于 jRaft 实现,随 NameServer 一起启动,用于 Broker 的自动主从切换
- **低配机仅用于选举**:192.168.3.110 节点仅部署 NameServer(包含 Controller),参与 Controller 集群选举,不部署 Broker
### 2.2 目录结构配置
#### 2.2.1 高性能机节点(192.168.3.230、192.168.3.200)执行
```bash
# 创建 Broker 相关目录
sudo mkdir -p /data/rocketmq/broker/{logs,store}
# 创建 NameServer 相关目录
sudo mkdir -p /data/rocketmq/nameserver/{logs,data}
# 设置目录权限(RocketMQ 容器默认用户 UID/GID 为 3000)
sudo chown 3000:3000 /data/rocketmq -R
```
#### 2.2.2 低配机节点(192.168.3.110)执行
```bash
# 仅创建 NameServer 相关目录(无需 Broker 目录)
sudo mkdir -p /data/rocketmq/nameserver/{logs,data}
# 设置目录权限
sudo chown 3000:3000 /data/rocketmq -R
```
---
## 三、部署架构说明
### 3.1 单节点部署(开发/测试环境)
适用于开发测试环境,部署单个 NameServer 和 Broker 实例:
- 1 个 NameServer 实例
- 1 个 Broker 实例(Master)
- 1 个 Dashboard 实例(可选)
**优点**:部署简单,资源占用少
**缺点**:无高可用,单点故障风险
### 3.2 集群部署(生产环境推荐)
适用于生产环境,部署多个实例组成高可用集群:
- 3 个 NameServer 实例(避免单点,3台机均部署)
- 2 个 Broker 实例(1 Master + 1 Slave,仅在2台高性能机部署)
- 3 个 Controller 实例(基于 jRaft,内嵌于 NameServer)
- 1 个 Dashboard 实例(可选,建议部署在高性能机)
**优点**:高可用、自动故障转移、负载均衡、资源优化
**缺点**:部署复杂,资源占用较多
**架构优势**:
- 低配机仅承担 NameServer 和 Controller 选举职责,资源占用低
- 高性能机专注处理 Broker 消息存储和转发,性能最大化
- Controller 集群跨3台机部署,确保选举的高可用性
---
## 四、Docker Compose 配置
### 4.1 NameServer 配置(所有3台节点统一执行)
创建 `/data/rocketmq/docker-compose.yml`,添加 NameServer 服务:
```yaml
version: "3.8"
networks:
my-net:
driver: bridge
services:
rocketmq-nameserver:
image: apache/rocketmq:5.3.2
container_name: rocketmq-nameserver
restart: always
deploy:
resources:
limits:
memory: 1G
replicas: 1
placement:
constraints:
- node.role == manager
networks:
- my-net
ports:
- "9876:9876" # NameServer 默认端口
- "9880:9880" # jRaft 内部通信端口
- "9770:9770" # Controller 外部通信端口
volumes:
- /etc/localtime:/etc/localtime
- /etc/timezone:/etc/timezone
- /data/rocketmq/nameserver/logs:/home/rocketmq/logs/rocketmqlogs
- /data/rocketmq/nameserver/data:/home/rocketmq/data
- /data/rocketmq/nameserver/namesrv.conf:/home/rocketmq/conf/namesrv.conf
environment:
- TZ=Asia/Hong_Kong
command: sh mqnamesrv -c /home/rocketmq/conf/namesrv.conf
```
**注意**:NameServer 配置在所有3台节点(192.168.3.230、192.168.3.200、192.168.3.110)都需要执行。
### 4.2 Broker 配置(仅2台高性能机执行)
在 `/data/rocketmq/docker-compose.yml` 中添加 Broker 服务:
```yaml
rocketmq-broker:
image: apache/rocketmq:5.3.2
container_name: rocketmq-broker
restart: always
deploy:
resources:
limits:
memory: 2G
networks:
- my-net
environment:
- TZ=Asia/Hong_Kong
ports:
- "10911:10911" # Broker 默认服务端口
- "10909:10909" # HA 端口(Master-Slave 同步)
- "18081:18081" # gRPC 代理端口
- "18080:18080" # HTTP 代理端口
volumes:
- /etc/localtime:/etc/localtime
- /etc/timezone:/etc/timezone
- /data/rocketmq/broker/logs:/home/rocketmq/logs/rocketmqlogs
- /data/rocketmq/broker/store:/home/rocketmq/store
- /data/rocketmq/broker/broker.conf:/home/rocketmq/broker.conf
- /data/rocketmq/broker/rmq-proxy.json:/home/rocketmq/rocketmq-5.3.2/conf/rmq-proxy.json
command: sh mqbroker -c /home/rocketmq/broker.conf --enable-proxy
```
**注意**:Broker 配置仅在2台高性能机(192.168.3.230、192.168.3.200)执行,低配机(192.168.3.110)不需要部署 Broker。
### 4.3 Dashboard 配置(可选,建议在高性能机部署)
在 `/data/rocketmq/docker-compose.yml` 中添加 Dashboard 服务:
```yaml
rocketmq-dashboard:
image: apacherocketmq/rocketmq-dashboard
container_name: rocketmq-dashboard
restart: always
deploy:
resources:
limits:
memory: 512M
replicas: 1
placement:
constraints:
- node.role == manager
networks:
- my-net
ports:
- "8086:8080"
volumes:
- /etc/localtime:/etc/localtime
- /etc/timezone:/etc/timezone
environment:
- JAVA_OPTS=-Xmx512M -Xms256M -Xmn128M -Drocketmq.namesrv.addr=192.168.3.230:9876;192.168.3.200:9876;192.168.3.110:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false
```
**注意**:Dashboard 建议部署在高性能机(如 192.168.3.230),仅需部署1个实例即可。
---
## 五、核心配置文件
### 5.1 NameServer 配置(所有3台节点统一执行)
创建 `/data/rocketmq/nameserver/namesrv.conf`:
```properties
# NameServer 监听端口
listenPort = 9876
# 启用内嵌 Controller(5.x 新特性)
enableControllerInNamesrv = true
# jRaft 内核配置(三台节点统一)
controllerType = jRaft
# 集群唯一标识
jRaftGroupId = controller-jraft-group
# Raft 内部通信地址(对应容器 9880 端口)
jRaftInitConf = 192.168.3.230:9880,192.168.3.200:9880,192.168.3.110:9880
# Controller 外部通信地址(对应容器 9770 端口)
jRaftControllerRPCAddr = 192.168.3.230:9770,192.168.3.200:9770,192.168.3.110:9770
# 标志自己节点的 ServerId,必须出现在 jRaftInitConf 中
# 每个节点需要修改为对应的主机 IP
jRaftServerId = 192.168.3.200:9880
# Controller 数据存储路径
controllerStorePath = /home/rocketmq/data
```
**注意**:每个节点的 `jRaftServerId` 需要修改为对应的主机 IP,例如:
- 节点1(192.168.3.230):`jRaftServerId = 192.168.3.230:9880`
- 节点2(192.168.3.200):`jRaftServerId = 192.168.3.200:9880`
- 节点3(192.168.3.110):`jRaftServerId = 192.168.3.110:9880`
### 5.2 Broker 配置(仅2台高性能机执行)
创建 `/data/rocketmq/broker/broker.conf`:
```properties
# ========== 节点标识配置(每个节点不同) ==========
# 节点 ID,0 表示 Master,其他正整数表示 Slave
brokerId = 1
# Broker 节点名称,集群部署时同一主从对的名称相同
brokerName = broker
# ========== Controller 模式配置 ==========
# Broker Controller 模式的总开关,只有该值为 true,自动主从切换模式才会打开
enableControllerMode = true
# Controller 地址列表(多个用 ; 隔开)
controllerAddr = 192.168.3.230:9770;192.168.3.200:9770;192.168.3.110:9770
# ========== NameServer 配置 ==========
# NameServer 地址列表(多个用 ; 隔开)
namesrvAddr = 192.168.3.230:9876;192.168.3.200:9876;192.168.3.110:9876
# ========== 集群配置 ==========
# 集群名称,同一集群中必须一致
brokerClusterName = DefaultCluster
# ========== 网络配置 ==========
# Broker 对外服务的监听端口(默认 10911)
# 注意:Broker 启动后会占用 3 个端口(listenPort-2、listenPort、listenPort+1)
listenPort = 10911
# Broker 服务地址(内部使用填内网 IP,外部使用填公网 IP)
brokerIP1 = 192.168.3.200
# BrokerHAIP 地址,供 Slave 同步消息的地址
# brokerIP2 = 127.0.0.1
# ========== 主从复制配置 ==========
# Broker 角色
# ASYNC_MASTER:异步复制 Master,主写成功即响应,可能丢失少量数据
# SYNC_MASTER:同步双写 Master,主从都写成功才响应,不会丢失数据
# SLAVE:从节点
brokerRole = ASYNC_MASTER
# 刷盘方式
# SYNC_FLUSH:同步刷新,性能较差但可靠性高
# ASYNC_FLUSH:异步刷新,性能好但可能丢失少量数据
flushDiskType = ASYNC_FLUSH
# ========== 消息存储配置 ==========
# 每天什么时间删除超过保留时间的 commit log(默认 04 点)
deleteWhen = 04
# 文件保留时间(小时,默认 72 小时)
fileReservedTime = 24
# 消息最大大小(字节,默认 4MB)
maxMessageSize = 4194304
# ========== Topic 配置 ==========
# 自动创建 Topic 时的默认队列数
defaultTopicQueueNums = 4
# 是否允许 Broker 自动创建 Topic(建议线下开启,线上关闭)
autoCreateTopicEnable = true
# 是否允许 Broker 自动创建订阅组(建议线下开启,线上关闭)
autoCreateSubscriptionGroup = true
# ========== 延时消息配置 ==========
# 延时等级(从 1 开始,可自定义添加如 1d)
messageDelayLevel = 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
# ========== 事务消息配置 ==========
# TM 在 20 秒内应将最终确认状态发送给 TC,否则引发消息回查(默认 60 秒)
transactionTimeout = 20
# 最多回查 5 次,超过后丢弃消息并记录错误日志(默认 15 次)
transactionCheckMax = 5
# 消息回查的时间间隔为 10 秒(默认 60 秒)
transactionCheckInterval = 10
# ========== 其他配置 ==========
# 延时消息最大时长(秒,默认 3 天,这里设置为 7 天)
timerMaxDelaySec = 604800
# 开启消息追踪
traceTopicEnable = true
```
**注意**:每个节点需要修改以下参数:
- `brokerId`:高性能机1(192.168.3.230)为 0(Master),高性能机2(192.168.3.200)为 1(Slave)
- `brokerIP1`:当前节点的主机 IP
**配置示例**:
- 高性能机1(192.168.3.230):`brokerId = 0`,`brokerIP1 = 192.168.3.230`
- 高性能机2(192.168.3.200):`brokerId = 1`,`brokerIP1 = 192.168.3.200`
- 低配机(192.168.3.110):不需要部署 Broker
### 5.3 Proxy 配置(仅2台高性能机执行)
创建 `/data/rocketmq/broker/rmq-proxy.json`:
```json
{
"rocketMQClusterName": "DefaultCluster",
"remotingListenPort": 18080,
"grpcServerPort": 18081,
"namesrvAddr": "192.168.3.200:9876;192.168.3.230:9876;192.168.3.110:9876"
}
```
**注意**:`namesrvAddr` 可以配置为当前节点优先的 NameServer 地址列表。
---
## 六、端口说明
### 6.1 NameServer 端口
| 端口 | 用途 | 说明 |
| :--- | :---------------------- | :----------------------------------------- |
| 9876 | NameServer 服务端口 | 客户端和 Broker 连接 NameServer 的默认端口 |
| 9880 | jRaft 内部通信端口 | Controller 集群内部 Raft 协议通信 |
| 9770 | Controller 外部通信端口 | Broker 连接 Controller 的 RPC 端口 |
### 6.2 Broker 端口
| 端口 | 用途 | 说明 |
| :---- | :------------------ | :------------------------------------------ |
| 10911 | Broker 默认服务端口 | 客户端发送和接收消息的默认端口 |
| 10909 | HA 端口 | Master-Slave 主从同步端口(listenPort - 2) |
| 10912 | Fast Fail 端口 | 快速失败端口(listenPort + 1,自动占用) |
| 18080 | HTTP 代理端口 | Proxy HTTP 协议接入端口 |
| 18081 | gRPC 代理端口 | Proxy gRPC 协议接入端口 |
### 6.3 Dashboard 端口
| 端口 | 用途 | 说明 |
| :--- | :----------------- | :-------------------------- |
| 8086 | Dashboard Web 界面 | RocketMQ 管理控制台访问端口 |
**注意**:部署集群时需要确保所有节点的端口不冲突,建议提前规划端口分配。
---
## 七、Controller 模式详解
### 7.1 Controller 模式架构
Controller 模式基于 jRaft 实现,采用 Raft 一致性算法,确保元数据的一致性和高可用:
```
+-----------------+
| Client App |
+--------+--------+
|
v
+--------------------+--------------------+
| | |
+-------v-------+ +-------v-------+ +-------v-------+
| NameServer | | NameServer | | NameServer |
| (高性能机1) | | (高性能机2) | | (低配机) |
| (Node1) | | (Node2) | | (Node3) |
+-------+-------+ +-------+-------+ +-------+-------+
| | |
+--------------------+--------------------+
|
+--------v--------+
| Controller | (jRaft 集群)
| (Leader) |
+--------+--------+
|
+--------------------+
|
+-------v-------+
| Broker | (高性能机1)
| (Master) |
+---------------+
|
v
+---------------+
| Broker | (高性能机2)
| (Slave) |
+---------------+
```
**架构说明**:
- **3台 NameServer**:所有节点都部署 NameServer,确保服务注册发现的高可用
- **Controller 内嵌于 NameServer**:Controller 基于 jRaft 实现,随 NameServer 一起启动
- **2台 Broker**:仅在2台高性能机部署 Broker,低配机仅参与选举
- **自动主从切换**:当 Master 故障时,Controller 自动选举 Slave 为新 Master
### 7.2 Controller 核心功能
1. **自动主从切换**
- 监控 Broker 健康状态
- Master 故障时自动选举新 Master
- 更新 NameServer 路由信息
2. **元数据管理**
- 统一管理 Topic、订阅组等元数据
- 避免元数据不一致问题
- 支持动态扩缩容
3. **负载均衡**
- 自动进行 Broker 负载均衡
- 优化集群资源利用率
- 支持流量调度
### 7.3 jRaft 配置说明
| 配置项 | 说明 | 示例值 |
| :----------------------- | :-------------------------- | :--------------------------------------------------------- |
| `controllerType` | Controller 实现类型 | `jRaft` |
| `jRaftGroupId` | Raft 集群唯一标识 | `controller-jraft-group` |
| `jRaftInitConf` | Raft 内部通信地址列表 | `192.168.3.230:9880,192.168.3.200:9880,192.168.3.110:9880` |
| `jRaftControllerRPCAddr` | Controller 外部通信地址列表 | `192.168.3.230:9770,192.168.3.200:9770,192.168.3.110:9770` |
| `jRaftServerId` | 当前节点的 ServerId | `192.168.3.200:9880` |
**注意**:
- `jRaftServerId` 必须出现在 `jRaftInitConf` 中
- 建议至少 3 个节点组成 Raft 集群,确保高可用
- Raft 集群会自动选举 Leader,无需手动指定
---
## 八、安全配置(可选)
### 8.1 ACL 认证配置
生产环境建议开启 ACL 认证,防止未授权访问。
#### 8.1.1 启用 ACL 认证
在 `broker.conf` 中添加:
```properties
# 开启 ACL 认证
aclEnable = true
# 指定 ACL 配置文件路径
globalWhiteRemoteAddresses = 127.0.0.1
```
#### 8.1.2 创建 ACL 配置文件
创建 `/data/rocketmq/broker/plain_acl.yml`:
```yaml
# 全局白名单(允许访问的 IP 地址)
globalWhiteRemoteAddresses:
- 10.*.*.*
- 192.168.*.*
# 账户配置
accounts:
# 管理员账户
- accessKey: admin
secretKey: admin123
whiteRemoteAddress:
admin: true
# 普通用户账户
- accessKey: appuser
secretKey: appuser123
whiteRemoteAddress:
admin: false
defaultTopicPerm: PUB|SUB
defaultGroupPerm: PUB|SUB
topicPerms:
- topicA=PUB
- topicB=SUB
groupPerms:
- groupA=PUB|SUB
```
#### 8.1.3 挂载 ACL 配置文件
在 `docker-compose.yml` 中添加 ACL 配置文件挂载:
```yaml
volumes:
- /data/rocketmq/broker/plain_acl.yml:/home/rocketmq/conf/plain_acl.yml
```
### 8.2 TLS/SSL 加密(可选)
生产环境建议开启 TLS/SSL 加密,保障数据传输安全。
#### 8.2.1 生成证书
```bash
# 生成 CA 证书
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/CN=RocketMQ CA"
# 生成服务器证书
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=192.168.3.200"
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
# 生成客户端证书
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/CN=Client"
openssl x509 -req -days 3650 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt
```
#### 8.2.2 配置 TLS
在 `broker.conf` 中添加:
```properties
# 开启 TLS
tlsTestModeEnable = false
tlsServerCert = /home/rocketmq/conf/server.crt
tlsServerKey = /home/rocketmq/conf/server.key
tlsServerAuthClient = true
tlsClientCertPath = /home/rocketmq/conf/ca.crt
```
挂载证书文件:
```yaml
volumes:
- /data/rocketmq/broker/server.crt:/home/rocketmq/conf/server.crt
- /data/rocketmq/broker/server.key:/home/rocketmq/conf/server.key
- /data/rocketmq/broker/ca.crt:/home/rocketmq/conf/ca.crt
```
---
## 九、启动和验证
### 9.1 启动服务
#### 9.1.1 启动 NameServer(所有3台节点执行)
```bash
# 进入目录
cd /data/rocketmq
# 启动 NameServer
docker compose up -d rocketmq-nameserver
# 查看启动状态
docker compose ps
```
#### 9.1.2 启动 Broker(仅2台高性能机执行)
```bash
# 进入目录
cd /data/rocketmq
# 启动 Broker
docker compose up -d rocketmq-broker
# 查看启动状态
docker compose ps
```
#### 9.1.3 启动 Dashboard(可选,建议在高性能机执行)
```bash
# 进入目录
cd /data/rocketmq
# 启动 Dashboard
docker compose up -d rocketmq-dashboard
# 查看启动状态
docker compose ps
```
**启动顺序建议**:
1. 先在所有3台节点启动 NameServer
2. 等待 NameServer 启动完成(约 30 秒)
3. 再在2台高性能机启动 Broker
4. 最后启动 Dashboard(可选)
### 9.2 验证 NameServer
```bash
# 查看日志(所有3台节点执行)
docker logs rocketmq-nameserver
# 测试连接
telnet 192.168.3.230 9876
telnet 192.168.3.200 9876
telnet 192.168.3.110 9876
```
### 9.3 验证 Broker
```bash
# 查看日志(仅2台高性能机执行)
docker logs rocketmq-broker
# 检查 Broker 是否注册到 NameServer
docker exec rocketmq-nameserver sh mqadmin clusterList -n 192.168.3.230:9876
# 查看集群状态(应该看到 2 个 Broker)
docker exec rocketmq-nameserver sh mqadmin brokerStatus -n 192.168.3.230:9876
```
### 9.4 验证 Controller
```bash
# 查看 Controller 状态(所有3台节点执行)
docker exec rocketmq-nameserver sh mqadmin getControllerMode -n 192.168.3.230:9876
# 查看 Controller 集群状态
docker exec rocketmq-nameserver sh mqadmin getControllerInfo -n 192.168.3.230:9876
```
**预期结果**:
- Controller 模式应显示为 `ENABLED`
- Controller 集群应选举出 Leader(3台节点中选1个)
### 9.5 访问 Dashboard
浏览器访问:`http://192.168.3.230:8086`
默认账号密码:`admin / admin`
**验证内容**:
- 集群概览中应显示 2 个 Broker
- NameServer 列表中应显示 3 个节点
- Controller 状态应为正常
---
## 十、常见问题
### 10.1 Broker 无法连接 NameServer
**现象**:Broker 日志显示连接 NameServer 失败
**排查步骤**:
1. 检查 `namesrvAddr` 配置是否正确
2. 检查防火墙是否开放 9876 端口
3. 检查网络连通性:`telnet <nameserver-ip> 9876`
### 10.2 Controller 集群无法选举 Leader
**现象**:Controller 集群一直处于选举状态
**排查步骤**:
1. 检查 `jRaftInitConf` 和 `jRaftServerId` 配置是否正确
2. 检查 9880 和 9770 端口是否开放
3. 检查节点时间是否同步(NTP)
4. 查看 NameServer 日志:`docker logs rocketmq-nameserver`
### 10.3 主从切换失败
**现象**:Master 故障后无法自动切换
**排查步骤**:
1. 检查 `enableControllerMode` 是否为 `true`
2. 检查 Controller 集群状态是否正常
3. 检查 Slave 节点是否正常运行
4. 查看 Broker 日志:`docker logs rocketmq-broker`
### 10.4 消息发送失败
**现象**:客户端发送消息超时或失败
**排查步骤**:
1. 检查 NameServer 地址配置是否正确
2. 检查 Topic 是否存在(`autoCreateTopicEnable` 是否开启)
3. 检查 Broker 是否正常注册到 NameServer
4. 检查网络连通性和防火墙规则
### 10.5 磁盘空间不足
**现象**:Broker 日志显示磁盘空间不足
**解决方案**:
1. 调整 `fileReservedTime` 参数,缩短消息保留时间
2. 调整 `deleteWhen` 参数,增加清理频率
3. 扩容磁盘空间
4. 手动清理过期消息:`docker exec rocketmq-broker sh mqadmin cleanExpiredCQFile -n <nameserver-addr>`
---
## 十一、性能优化建议
### 11.1 JVM 参数优化
在 `docker-compose.yml` 中调整 JVM 参数:
```yaml
environment:
- JAVA_OPT_EXT=-Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m
```
### 11.2 操作系统优化
```bash
# 增加文件描述符限制
ulimit -n 65535
# 优化 TCP 参数
echo 'net.core.somaxconn = 1024' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_max_syn_backlog = 2048' >> /etc/sysctl.conf
sysctl -p
```
### 11.3 网络优化
- 使用万兆网络(10Gbps)
- 部署在同一机房,减少网络延迟
- 使用专用网络,避免公网访问
### 11.4 存储优化
- 使用 SSD 存储,提升 IO 性能
- 将日志和数据分离到不同磁盘
- 定期清理过期消息,避免磁盘满
---
## 十二、监控和告警
### 12.1 关键监控指标
| 指标 | 说明 | 告警阈值 |
| :---------------- | :------------------- | :------- |
| 消息堆积量 | 消息未消费数量 | > 10000 |
| 消息发送 TPS | 每秒发送消息数 | 异常波动 |
| 消息消费 TPS | 每秒消费消息数 | 异常波动 |
| Broker CPU 使用率 | Broker 进程 CPU 占用 | > 80% |
| Broker 内存使用率 | Broker 进程内存占用 | > 80% |
| 磁盘使用率 | 数据目录磁盘占用 | > 80% |
| 网络流量 | 网络入出流量 | 异常波动 |
### 12.2 日志监控
- Broker 日志:`/data/rocketmq/broker/logs/`
- NameServer 日志:`/data/rocketmq/nameserver/logs/`
建议使用 ELK 或 Loki 等日志收集系统进行集中管理。
---
## 十三、备份和恢复
### 13.1 数据备份
```bash
# 备份 Broker 数据
tar -czf rocketmq-broker-backup-$(date +%Y%m%d).tar.gz /data/rocketmq/broker/store
# 备份配置文件
tar -czf rocketmq-config-backup-$(date +%Y%m%d).tar.gz /data/rocketmq/broker/*.conf /data/rocketmq/broker/*.json
```
### 13.2 数据恢复
```bash
# 停止 Broker
docker compose stop rocketmq-broker
# 恢复数据
tar -xzf rocketmq-broker-backup-20240121.tar.gz -C /
# 启动 Broker
docker compose start rocketmq-broker
```
---
## 十四、升级和扩容
### 14.1 版本升级
```bash
# 1. 停止服务
docker compose down
# 2. 备份数据
tar -czf rocketmq-backup-$(date +%Y%m%d).tar.gz /data/rocketmq
# 3. 更新镜像版本
sed -i 's/apache\/rocketmq:5.3.2/apache\/rocketmq:5.3.3/g' docker-compose.yml
# 4. 启动服务
docker compose up -d
# 5. 验证服务
docker compose ps
```
### 14.2 集群扩容
```bash
# 1. 在新节点创建目录
sudo mkdir -p /data/rocketmq/broker/{logs,store}
sudo mkdir -p /data/rocketmq/nameserver/{logs,data}
sudo chown 3000:3000 /data/rocketmq -R
# 2. 复制配置文件到新节点
scp /data/rocketmq/broker/broker.conf root@<new-node>:/data/rocketmq/broker/
scp /data/rocketmq/nameserver/namesrv.conf root@<new-node>:/data/rocketmq/nameserver/
# 3. 修改新节点配置(brokerId、brokerIP1、jRaftServerId 等)
# 4. 在新节点启动服务
cd /data/rocketmq && docker compose up -d
# 5. 验证新节点注册
docker exec rocketmq-nameserver sh mqadmin clusterList -n 192.168.3.230:9876
```
---
## 十五、总结
### 15.1 部署检查清单
#### 15.1.1 所有3台节点(192.168.3.230、192.168.3.200、192.168.3.110)
- [ ] NameServer 目录创建完成(`/data/rocketmq/nameserver/{logs,data}`)
- [ ] NameServer 目录权限设置正确(`chown 3000:3000 /data/rocketmq -R`)
- [ ] NameServer 配置文件正确(`/data/rocketmq/nameserver/namesrv.conf`)
- [ ] jRaftServerId 配置唯一(每个节点对应自己的 IP)
- [ ] Docker Compose 配置文件正确(包含 NameServer 服务)
- [ ] 防火墙规则配置正确(9876、9880、9770 端口开放)
- [ ] NameServer 启动成功,日志无错误
- [ ] NameServer 之间网络互通
#### 15.1.2 高性能机节点(192.168.3.230、192.168.3.200)
- [ ] Broker 目录创建完成(`/data/rocketmq/broker/{logs,store}`)
- [ ] Broker 目录权限设置正确(`chown 3000:3000 /data/rocketmq -R`)
- [ ] Broker 配置文件正确(`/data/rocketmq/broker/broker.conf`)
- [ ] brokerId 配置正确(192.168.3.230 为 0,192.168.3.200 为 1)
- [ ] brokerIP1 配置正确(对应当前节点 IP)
- [ ] Proxy 配置文件正确(`/data/rocketmq/broker/rmq-proxy.json`)
- [ ] Docker Compose 配置文件正确(包含 Broker 服务)
- [ ] 防火墙规则配置正确(10911、10909、18080、18081 端口开放)
- [ ] Broker 启动成功,日志无错误
- [ ] Broker 成功注册到所有 NameServer
#### 15.1.3 Dashboard 节点(建议在 192.168.3.230)
- [ ] Docker Compose 配置文件正确(包含 Dashboard 服务)
- [ ] 防火墙规则配置正确(8086 端口开放)
- [ ] Dashboard 启动成功
- [ ] Dashboard 可以正常访问(`http://192.168.3.230:8086`)
#### 15.1.4 集群整体验证
- [ ] 3 个 NameServer 都正常运行
- [ ] 2 个 Broker 都正常运行
- [ ] Controller 集群选举成功(有 1 个 Leader)
- [ ] Controller 模式已启用(`ENABLED`)
- [ ] Broker 主从关系正常(1 Master + 1 Slave)
- [ ] Dashboard 显示集群状态正常
### 15.2 最佳实践
1. **架构设计**:
- 3台 NameServer 确保服务注册发现的高可用
- 2台 Broker 部署在高性能机,低配机仅参与选举
- Controller 跨3台机部署,确保选举的高可用性
2. **数据可靠性**:根据业务需求选择 `brokerRole` 和 `flushDiskType`
3. **监控告警**:建立完善的监控和告警机制,及时发现异常
4. **定期备份**:定期备份配置文件和数据,防止数据丢失
5. **安全加固**:生产环境建议开启 ACL 认证和 TLS 加密
6. **性能优化**:根据实际负载调整 JVM 参数和系统参数
7. **日志管理**:定期清理日志,避免磁盘满
8. **资源规划**:低配机仅部署 NameServer,高性能机部署 Broker,资源利用率最大化
---
**参考资料**:
- [RocketMQ 官方文档](https://rocketmq.apache.org/zh/docs/)
- [RocketMQ 5.x Controller 模式介绍](https://rocketmq.apache.org/zh/docs/featureBehavior/05controller)
- [jRaft 官方文档](https://github.com/sofastack/sofa-jraft)
@@ -0,0 +1,120 @@
# FIX Engine 高可用 (HA) 架构方案说明文档
## 1. 架构演进概述
### 1.1 原单实例架构
- **消息存储**: 使用本地文件系统(FileStore),消息持久化在本地磁盘。
- **灾备能力**: 无自动切换机制。若实例宕机,需手动启动备机,且由于文件存储不共享,消息序列号(Sequence Number)难以同步。
- **会话管理**: 启动即连接,缺乏灵活性。
### 1.2 现高可用 (HA) 架构
- **消息存储**: 迁移至 **MySQL 数据库**(JdbcStore)。多实例共享同一数据库,确保消息和序列号在节点切换后保持一致。
- **领导权选举**: 引入 **Redis 分布式锁**(Redisson)。以 Session 为粒度进行选举,确保每个 FIX 会话在全网只有一个活动实例。
- **自动灾备**: 备机定时检查锁状态,主节点宕机后锁释放,备机自动接管并恢复连接。
- **动态会话**: 结合 DynamicSession 机制,仅在获得领导权后才创建并启动 FIX 连接。
---
## 2. 核心组件分析
### 2.1 MySQL 消息持久化 (JdbcStore)
通过 `QuickFixJConfig` 配置,系统支持将消息存储从文件切换到 MySQL。
- **核心类**: `quickfix.JdbcStoreFactory`
- **配置触发**: 当 `StorageType=mysql` 时启用。
- **数据表要求**: 需要在数据库中创建 QuickFIX/J 标准表(如 `messages`, `sessions` 等)。
- **优势**:
- **共享状态**: 所有实例访问同一份数据,切换节点无需手动同步序列号。
- **可靠性**: 数据库事务保障消息持久化。
### 2.2 Redis 分布式锁选举 (LeaderElectionService)
使用 Redisson 实现 Session 级别的分布式锁管理。
- **锁 Key 格式**: `g3fo:fix-engine:session-lock:{SenderCompID}@{TargetCompID}`
- **看门狗机制**: 租约时间设为 -1,Redisson 自动续期。只要进程存活,锁就不会过期。
- **检查机制**: 定时线程(默认 10 秒)遍历所有配置的 Session。
- **宕机延迟 (Failover Delay)**: 检测到锁释放后,等待 5 秒再尝试抢占,防止因网络抖动引起的频繁切换。
### 2.3 动态会话控制 (Dynamic Session)
解决 QuickFIX/J 在 `start()` 时会自动连接所有会话的问题。
- **机制**: 在配置文件中将 Session 标记为 Dynamic(不预先加载)。
- **流程**:
1. `LeaderElectionService` 获得 Redis 锁。
2. 调用 `quickFixJConfig.startSession(sessionCode)`。
3. 内部通过 `socketInitiator.createDynamicSession(sessionId)` 动态创建会话对象。
4. 调用 `session.logon()` 触发连接。
---
## 3. 完整业务流程
### 3.1 服务启动流程
```mermaid
flowchart TD
Start([服务启动]) --> InitInitiator[初始化 QuickFIX Initiator]
InitInitiator --> StartElection[启动 LeaderElectionService]
StartElection --> LoadSessions[加载 enabledSession 配置]
LoadSessions --> LoopCheck{遍历每个 Session}
LoopCheck --> TryLock[尝试获取 Redis 分布式锁]
TryLock -- 成功获得锁 --> StartComp[启动会话组件]
StartComp --> CreateDynamic[创建 DynamicSession 对象]
CreateDynamic --> FixLogon[发送 FIX Logon]
FixLogon --> StartMQ[启动对应的 RocketMQ Listener]
TryLock -- 失败 --> Standby[进入待命状态]
Standby --> Wait[等待下一个检查周期]
Wait --> LoopCheck
```
### 3.2 宕机自动切换流程 (Failover)
1. **主节点 (Node A)** 持有 `A@OCG` 的 Redis 锁,正常运行。
2. **主节点 (Node A)** 宕机或网络断开。
3. **Redis 锁失效**: 经过看门狗租约超时,Redis 中的锁 Key 消失。
4. **备节点 (Node B)** 定时任务检测到锁已释放。
5. **进入延迟等待**: 备节点等待 `failoverDelay` (如 5秒)。
6. **抢占锁**: 备节点尝试 `tryLock`,成功获得领导权。
7. **恢复连接**: 备节点动态创建 Session 并在 MySQL 中读取最新的序列号,发送 Logon。
8. **流量接管**: 启动 MQ Listener,开始处理业务消息。
---
## 4. 关键配置指南 (Nacos)
在 `quick-fix-client.yml` 中进行如下配置:
```yaml
quickfixj:
client:
# 启用会话列表
enabledSession: A@OCG,A@OSL
# 选举参数
sessionElection:
checkInterval: 10 # 检查周期(秒)
failoverDelay: 5 # 接管延迟(秒)
# 存储配置(需配合数据源)
# 确保 SessionSettings 中的 StorageType=mysql
```
---
## 5. 日志监控与诊断
通过监控日志可以实时掌握 HA 状态:
| 日志内容 | 含义 | 级别 |
| :--- | :--- | :--- |
| `>>> 获得Session A@OCG 领导权 <<<` | 当前实例成功竞争到主节点 | INFO |
| `!!! Session A@OCG 领导权锁意外丢失 !!!` | 锁异常丢失,可能是 Redis 连接断开 | ERROR |
| `正在启动Session A@OCG 组件...` | 获得锁后开始加载 FIX 和 MQ | INFO |
| `✅ Session A@OCG 组件启动完成` | 成功恢复服务 | INFO |
| `未获得领导权,作为备用实例运行中...` | 当前为备份节点,正常待命 | DEBUG |
---
## 6. 总结
本方案通过 **MySQL 共享存储 + Redis 分布式选举 + 动态会话加载** 的组合,解决了 FIX 引擎单点故障问题。它不仅保证了消息的连续性(序列号一致),还实现了会话级别的细粒度高可用,能够灵活应对多种部署场景。
@@ -1,25 +1,31 @@
# Service Name: [Service ID]
# Service Name: g3fo-exchange-fix-engine-service
## 1. Overview
[A brief description of what this service does and its primary responsibility.]
g3fo-exchange-fix-engine-service 是 g3fo 系统的 FIX 协议接入引擎。它负责与外部交易所或交易对手建立 FIX 连接,进行消息的编码、解码、序列号维护以及消息的持久化存储。
## 2. Key Responsibilities
- [Responsibility 1]
- [Responsibility 2]
- [Responsibility 3]
- **会话管理**: 维护与外部实体的 FIX 会话,处理 Logon, Logout, Heartbeat, ResendRequest 等协议级消息。
- **消息路由**: 将接收到的 FIX 消息转换为内部业务格式并转发给下游服务,同时将下游服务的指令转换为 FIX 消息发送给外部。
- **消息持久化**: 记录所有发送和接收的 FIX 消息,确保在异常重启后能够恢复会话状态。
- **高可用 (HA)**: 支持基于 Redis 选举和 MySQL 共享存储的多实例部署。
## 3. Key Data Entities
[List major database tables or domain objects managed by this service.]
- **Entity A**: [Description]
- **Entity B**: [Description]
- **FIX 消息存储**: 存储在 MySQL 中的 `messages` 表(基于 JdbcStore)。
- **FIX 会话状态**: 存储在 MySQL 中的 `sessions` 表。
## 4. Dependencies
- **Upstream**: [Services that call this service]
- **Downstream**: [Services called by this service]
- **Middleware**: [e.g., MySQL, Redis, Kafka]
- **Upstream**: `g3fo-trade-service` (发送交易指令)
- **Downstream**: 外部交易所 FIX Gateway
- **Middleware**:
- **MySQL**: 用于消息持久化。
- **Redis**: 用于分布式锁选举。
- **RocketMQ**: 用于与其他微服务通信。
## 5. Critical Configurations
[Key environment variables or config items.]
- **QuickFIX/J 配置**: `quick-fix-client.yml` 中定义的会话参数、存储类型、选举参数等。
- **Nacos**: 动态配置中心,存储服务运行参数。
## 6. Common Operations / Troubleshooting
[Service-specific health check URLs, log locations, etc.]
- **高可用架构说明**: 详细的 HA 方案请参考 [FIX Engine 高可用 (HA) 架构方案说明文档](./fix-engine/ha-architecture.md)。
- **日志监控**: 重点关注 `LeaderElectionService` 的选举日志和 `quickfix.JdbcStore` 的数据库操作日志。
- **会话重置**: 手动重置序列号通常需要清理数据库中的 `sessions` 表对应记录并重启服务。