docs: update planb integrated deployment assets

This commit is contained in:
tangweijie 2026-04-01 15:51:07 +08:00
parent f8b75f7771
commit 5a1abd4c03
12 changed files with 963 additions and 99 deletions

View File

@ -57,7 +57,7 @@ retrieval_priority: P1
5. 两台业务应用节点内均部署 `Spring Boot Gateway`,作为微服务集群统一接入入口,并同时承载业务服务。
6. 中间件集中部署在 1 台主机上。
7. 数据库控制组件与中间件部署在同一台主机上。
8. `MinIO` 作为静态存储与对象存储统一入口,与中间件同机部署。
8. `RustFS` 作为静态存储与对象存储统一入口,与中间件同机部署。
9. 一期口径下,原“数据与中间件节点”和“文件存储节点”合并为 1 台综合节点。
10. 银行文件交换采用独立 `SFTP/FTP` 文件交换服务器,作为银行送盘、回盘、对账文件交换专用前置机。
11. 当前已知可用于本方案的业务与基础设施主机资源如下:
@ -88,11 +88,18 @@ flowchart LR
classDef access fill:#fff7ed,stroke:#ea580c,stroke-width:1.4px,color:#7c2d12;
classDef app fill:#eff6ff,stroke:#2563eb,stroke-width:1.4px,color:#1e3a8a;
U1[PC 端用户]:::source
U2[移动端用户]:::source
U3[第三方系统]:::source
G1[公网入口薄转发]:::access
G2[内网 Nginx]:::access
subgraph OUTER[公网域]
direction TB
U2[移动端用户]:::source
U3[第三方系统]:::source
G1[公网接入代理]:::access
end
subgraph INNER[内部网络域]
direction TB
U1[PC 端用户]:::source
G2[内网 Nginx]:::access
end
subgraph APP1[业务应用节点 1]
direction TB
@ -109,7 +116,7 @@ flowchart LR
U1 -->|内网访问| G2
U2 -->|HTTPS 443| G1
U3 -->|接口访问| G1
G1 -->|开放 API 转发| G2
G1 -->|跨公网/内网边界转发| G2
G2 -->|负载到节点 1| A1G
G2 -->|负载到节点 2| A2G
A1G --> A1B
@ -118,11 +125,12 @@ flowchart LR
图说明:
1. PC 端用户通过内网直接访问内网 Nginx。
2. 移动端用户和第三方系统先经公网入口薄转发,再由公网入口转发到内网 Nginx。
3. 内网 Nginx 将开放 API 端点负载到两台业务应用节点。
4. 两台业务应用节点内均部署 Spring Boot Gateway作为微服务集群统一接入入口。
5. 每台业务应用节点内的 Gateway 再向本节点业务服务转发请求。
1. 图中已明确区分公网域与内部网络域。
2. PC 端用户通过内网直接访问内部网络域中的内网 Nginx。
3. 移动端用户和第三方系统位于公网域,先经公网接入代理,再跨边界转发到内部网络域中的内网 Nginx。
4. 内网 Nginx 将开放 API 端点负载到两台业务应用节点。
5. 两台业务应用节点内均部署 Spring Boot Gateway作为微服务集群统一接入入口。
6. 每台业务应用节点内的 Gateway 再向本节点业务服务转发请求。
**图 4-2 综合服务软件拓扑图**
@ -136,7 +144,7 @@ flowchart TB
subgraph M[综合节点]
direction TB
M2[Redis / Nacos / MinIO]:::service
M2[Redis / Nacos / RustFS]:::service
M3[HAProxy / PgBouncer / Patroni]:::service
end
@ -160,7 +168,7 @@ flowchart LR
classDef backup fill:#fffbeb,stroke:#d97706,stroke-width:1.4px,color:#78350f;
classDef bank fill:#fef2f2,stroke:#dc2626,stroke-width:1.4px,color:#7f1d1d;
M2[MinIO / 附件文件]:::service
M2[RustFS / 文件归档]:::service
M3[HAProxy / PgBouncer / Patroni]:::service
F1[SFTP / FTP 文件交换服务器]:::bank
D1[(PostgreSQL 主库)]:::data
@ -181,7 +189,7 @@ flowchart LR
1. 数据库控制组件经由主库提供数据库访问能力。
2. 主库与热备之间通过同步复制保持一致性。
3. 银行文件交换服务器承接送盘、回盘、对账文件交换能力。
4. MinIO 与银行文件交换服务器分别将各自数据归档到备份归档存储。
4. RustFS 与银行文件交换服务器分别将各自数据归档到备份归档存储。
## 主机部署图
@ -217,7 +225,7 @@ flowchart LR
1. 内网 Nginx 入口节点作为我方统一接入入口,承接 API 转发与内部负载均衡能力。
2. 业务应用节点 1 和业务应用节点 2 组成应用主机集群,节点内同时部署 Spring Boot Gateway 与核心业务服务。
3. 综合节点集中承载 Redis、Nacos、MinIO、HAProxy、PgBouncer、Patroni并同时访问数据库主库与热备服务器。
3. 综合节点集中承载 Redis、Nacos、RustFS、HAProxy、PgBouncer、Patroni并同时访问数据库主库与热备服务器。
4. 独立的 SFTP/FTP 文件交换服务器承接银行送盘、回盘、对账文件交换,并由业务应用节点直接访问。
5. 数据库主库服务器与数据库热备服务器独立部署,满足数据库高可用要求。
@ -225,7 +233,7 @@ flowchart LR
1. 内网 Nginx 入口节点部署 `Nginx`,负责开放 API 转发和内部负载均衡。
2. 两台业务应用节点分别部署 `Spring Boot Gateway` 与业务服务实例。
3. 综合节点部署 `Redis``Nacos``MinIO`、`HAProxy``PgBouncer``Patroni`,并负责访问数据库主库与热备服务器。
3. 综合节点部署 `Redis``Nacos``RustFS`、`HAProxy``PgBouncer``Patroni`,并负责访问数据库主库与热备服务器。
4. SFTP/FTP 文件交换服务器部署银行文件交换服务及送盘、回盘、对账目录,由业务应用节点直接访问。
5. 数据库主库服务器部署 PostgreSQL 主库实例,数据库热备服务器部署 PostgreSQL 热备实例。
@ -268,107 +276,165 @@ flowchart LR
flowchart LR
DB1[(PostgreSQL 主库)] --> BK[备份归档存储]
DB2[(PostgreSQL 热备)] --> BK
MID[综合节点 / MinIO] --> BK
MID[综合节点 / RustFS] --> BK
BK --> REC[恢复与演练入口]
```
图说明:
1. 主库和热备均向备份归档存储输出备份数据。
2. 综合节点中的 MinIO 文件数据也纳入备份范围。
2. 综合节点中的 RustFS 文件数据也纳入备份范围。
3. 备份归档存储作为数据库恢复与文件恢复的统一入口。
## 网络拓扑图
**图 4-7 网络拓扑图**
> 说明:如需生成正式网络分区图与网络连接图,统一以 `scripts/generate_planb_diagrams.py` 生成的产物为准;其他脚本仅用于布局试验,不作为正式交付依据。
**图 4-7 网络分区图**
```mermaid
flowchart LR
classDef user fill:#ecfeff,stroke:#0891b2,stroke-width:1.2px,color:#083344;
classDef edge fill:#fff7ed,stroke:#ea580c,stroke-width:1.2px,color:#7c2d12;
classDef zone fill:#f8fafc,stroke:#94a3b8,stroke-width:1.2px,color:#0f172a;
classDef svc fill:#f5f3ff,stroke:#7c3aed,stroke-width:1.2px,color:#4c1d95;
classDef data fill:#ecfdf5,stroke:#059669,stroke-width:1.2px,color:#064e3b;
classDef bank fill:#fef2f2,stroke:#dc2626,stroke-width:1.2px,color:#7f1d1d;
classDef backup fill:#fffbeb,stroke:#d97706,stroke-width:1.2px,color:#78350f;
U[用户与外部系统]:::user
PGW[公网接入代理]:::edge
subgraph Z1[内网接入区]
IGW[内网 Nginx]
end
subgraph Z2[应用区]
APP[业务应用集群]
end
subgraph Z3[综合服务区]
MID[综合节点]
end
subgraph Z4[数据区]
DBM[(PostgreSQL 主库)]
DBS[(PostgreSQL 热备)]
end
subgraph Z6[互联网银行交换区]
FX[SFTP / FTP 文件交换服务器]
end
subgraph Z5[机房接入区]
BK[备份归档存储]
end
class Z1,Z2,Z3,Z4,Z5,Z6 zone;
class IGW edge;
class APP svc;
class MID svc;
class DBM,DBS data;
class FX bank;
class BK backup;
U --> PGW
U --> IGW
PGW --> IGW
IGW --> APP
APP --> FX
APP --> MID
MID --> DBM
MID --> DBS
DBM --> BK
DBS --> BK
MID --> BK
```
图说明:
1. 公网接入代理不纳入我方主机资源,但作为公网访问进入内网的前置接入层予以保留。
2. 网络分区图按服务器和服务器集群粒度表达,不展开单机内部软件组件。
3. PC 端用户可直接通过内网访问内网 Nginx移动端和第三方系统经公网接入代理后进入内网 Nginx。
4. 业务应用集群、综合服务区、数据区、机房接入区、互联网银行交换区相互隔离,通过授权链路互通。
**图 4-8 网络连接图**
```mermaid
flowchart TB
classDef user fill:#ecfeff,stroke:#0891b2,stroke-width:1.2px,color:#083344;
classDef access fill:#fff7ed,stroke:#ea580c,stroke-width:1.2px,color:#7c2d12;
classDef app fill:#eff6ff,stroke:#2563eb,stroke-width:1.2px,color:#1e3a8a;
classDef ext fill:#fef3c7,stroke:#d97706,stroke-width:1.2px,color:#78350f;
classDef middle fill:#f5f3ff,stroke:#7c3aed,stroke-width:1.2px,color:#4c1d95;
classDef data fill:#ecfdf5,stroke:#059669,stroke-width:1.2px,color:#064e3b;
classDef backup fill:#fdf2f8,stroke:#db2777,stroke-width:1.2px,color:#831843;
classDef backup fill:#fffbeb,stroke:#d97706,stroke-width:1.2px,color:#78350f;
classDef bank fill:#fef2f2,stroke:#dc2626,stroke-width:1.2px,color:#7f1d1d;
subgraph U[访问来源]
subgraph OUTER[公网域]
direction LR
PC[PC 端用户]
M[移动端用户]
T[第三方系统]
M[移动端用户]:::user
T[第三方系统]:::user
FX[SFTP/FTP文件交换服务器]:::bank
end
subgraph A[接入层]
subgraph INNER[内部网络域]
direction TB
PGW[公网入口薄转发]
IGW[内网 Nginx]
subgraph CLIENT[客户端]
PC[PC 端用户]:::user
end
subgraph ACCESS[接入层]
PGW[公网接入代理]:::access
IGW[内网 Nginx]:::access
end
subgraph SVC[应用与中间件层]
APP[业务应用集群<br/>Spring Boot Gateway + Biz]:::app
CACHE[Redis / Nacos / RustFS]:::middle
CTRL[HAProxy / PgBouncer / Patroni]:::middle
end
subgraph DATA[数据层]
DBM[(PostgreSQL 主库)]:::data
DBS[(PostgreSQL 热备)]:::data
end
subgraph STORAGE[存储层]
STORE[备份归档存储]:::backup
end
end
subgraph B[应用层]
direction LR
APP1[业务应用节点 1<br/>Spring Boot Gateway]
APP2[业务应用节点 2<br/>Spring Boot Gateway]
end
subgraph E[外部交换区]
direction TB
FX[SFTP/FTP 文件交换服务器]
end
subgraph C[综合服务层]
direction TB
MID[综合节点]
end
subgraph D[数据层]
direction LR
DBM[(PostgreSQL 主库)]
DBS[(PostgreSQL 热备)]
end
subgraph BK[备份归档层]
direction TB
STORE[备份归档存储]
end
%% 公网访问链路
M -->|HTTPS 443| PGW
T -->|HTTPS 443 / 接口| PGW
PGW -->|请求转发| IGW
%% 内网访问链路
PC -->|内网访问| IGW
M -->|公网 HTTPS| PGW
T -->|公网 HTTPS/接口| PGW
PGW -->|转发| IGW
IGW -->|网关/应用端口| APP
IGW -->|负载均衡| APP1
IGW -->|负载均衡| APP2
APP1 -->|文件交换| FX
APP2 -->|文件交换| FX
APP1 -->|业务访问| MID
APP2 -->|业务访问| MID
MID -->|数据库访问| DBM
MID -->|状态感知/只读访问| DBS
%% 应用层依赖
APP -->|6379 / 8848 / 9000| CACHE
APP -->|文件传输| FX
APP -->|6432 / 5000| CTRL
CTRL -->|5432| DBM
CTRL -.->|5432 状态探测| DBS
DBM -->|主备同步| DBS
DBM -->|备份/WAL 归档| STORE
DBS -->|备份副本| STORE
MID -->|文件归档| STORE
class PC,M,T user;
class PGW,IGW access;
class APP1,APP2 app;
class FX ext;
class MID middle;
class DBM,DBS data;
class STORE backup;
%% 数据备份与归档
CACHE -->|归档文件| STORE
DBM -->|备份 / WAL 归档| STORE
DBS -.->|备份副本| STORE
```
图说明:
1. PC 端用户通过内网直接访问内网 Nginx移动端用户和第三方系统通过公网入口薄转发再转发至内网 Nginx。
2. 内网 Nginx 统一负载到两台业务应用节点,两台节点内部均部署 Spring Boot Gateway。
3. 业务应用节点一方面直接访问 SFTP/FTP 文件交换服务器,另一方面访问综合节点获取缓存、配置、文件和数据库代理能力。
4. 综合节点访问 PostgreSQL 主库与热备,数据库主备及综合节点均接入备份归档存储。
1. 图中已明确区分公网域与内部网络域,公网访问通过公网接入代理跨边界进入内部网络。
2. PC 端用户位于内部网络域,直接访问内网 Nginx移动端和第三方系统位于公网域。
3. 内网 Nginx 统一将 API / Gateway 请求负载到业务应用集群。
4. 业务应用集群分别访问综合服务、银行文件交换服务器和数据库控制组件。
5. 综合服务中的数据库控制组件同时访问 PostgreSQL 主库与热备;数据库与综合服务均向备份归档存储输出归档数据。
## 主机角色与部署内容
@ -376,7 +442,7 @@ flowchart TB
|---|---|---:|---|---|
| 接入层 | 内网 Nginx 入口节点 | 1 台 | Nginx、API 转发、内部负载均衡 | 作为我方统一内网接入入口,承接开放 API 转发 |
| 应用层 | 业务应用节点(主) | 2 台 | Spring Boot Gateway、Spring Boot 业务服务 | 承载微服务集群接入与表务、抄表、收费、账务、发票、报表等核心应用服务 |
| 综合支撑层 | 数据、中间件与文件存储综合节点 | 1 台 | Redis、Nacos、MinIO、HAProxy、PgBouncer、Patroni | 中间件、数据库控制与文件存储同机部署 |
| 综合支撑层 | 数据、中间件与文件存储综合节点 | 1 台 | Redis、Nacos、RustFS、HAProxy、PgBouncer、Patroni | 中间件、数据库控制与文件存储同机部署 |
| 银行交换层 | SFTP/FTP 文件交换服务器 | 1 台 | SFTP/FTP 服务、送盘目录、回盘目录、对账目录、归档目录 | 作为银行文件交换专用前置机 |
| 数据库层 | PostgreSQL 主库服务器 | 1 台 | PostgreSQL 16 Primary | 部署在可用区 A |
| 数据库层 | PostgreSQL 热备服务器 | 1 台 | PostgreSQL 16 Standby | 部署在可用区 B |
@ -419,7 +485,7 @@ flowchart TB
|---|---:|---:|---|---|---|---|
| 1 | 内网 Nginx 入口节点 | 1 台 | 8 核 CPU / 16 GB 内存 / 300 GB 存储 | Nginx、API 转发、内部负载均衡 | 我方统一内网接入入口 | 可利旧优先 |
| 2 | 业务应用节点(主) | 2 台 | 32 核 CPU / 64 GB 内存 / 300 GB 存储 | Spring Boot Gateway、Spring Boot 核心业务服务 | 承载微服务接入与核心业务服务 | 现有资源纳入正式方案 |
| 3 | 数据、中间件与文件存储综合节点 | 1 台 | 16 核 CPU / 32 GB 内存 / 2300 GB 存储 | Redis、Nacos、MinIO、HAProxy、PgBouncer、Patroni | 承载缓存、配置治理、数据库控制、图片、附件、导出文件等能力 | 现有资源纳入正式方案 |
| 3 | 数据、中间件与文件存储综合节点 | 1 台 | 16 核 CPU / 32 GB 内存 / 2300 GB 存储 | Redis、Nacos、RustFS、HAProxy、PgBouncer、Patroni | 承载缓存、配置治理、数据库控制、图片、附件、导出文件等能力 | 现有资源纳入正式方案 |
| 4 | SFTP/FTP 文件交换服务器 | 1 台 | 2 核 CPU / 8 GB 内存 / 200 GB 存储 | SFTP/FTP 服务、送盘/回盘/对账目录、归档目录 | 承载银行文件交换与目录隔离 | 按最节约一期规划建议新增或单独利旧 |
| 5 | PostgreSQL 主库服务器 | 1 台 | 24 核 CPU / 48 GB 内存 / 1 TB NVMe SSD | PostgreSQL 16 Primary | 承载生产写入 | 建议单独配置 |
| 6 | PostgreSQL 热备服务器 | 1 台 | 24 核 CPU / 48 GB 内存 / 1 TB NVMe SSD | PostgreSQL 16 Standby | 承载正式切换接管 | 建议单独配置 |
@ -436,7 +502,7 @@ flowchart TB
| 类别 | 软件名称 | 建议版本 | 部署位置 | 说明 |
|---|---|---|---|---|
| 操作系统 | Linux 发行版 | openEuler 20.03+ / CentOS 7.9+ | 全部服务器 | 按甲方基础环境标准选定 |
| 操作系统 | Linux 发行版 | 银河麒麟Kylin V10X86 | 全部服务器 | 按甲方当前基础环境标准选定 |
| 运行环境 | JDK | 17 | 业务应用节点 | Spring Boot 运行环境 |
| 接入层 | Nginx | 1.20+ | 内网 Nginx 入口节点 | 内网 API 转发、内部负载均衡 |
| 网关服务 | Spring Boot Gateway | 3.x | 业务应用节点 | 微服务集群统一接入 |
@ -445,7 +511,7 @@ flowchart TB
| 数据库 | PostgreSQL | 16 | 主库、热备库 | 主备数据库部署 |
| 缓存 | Redis | 6.2+ | 综合节点 | 缓存、会话、轻量级消息能力 |
| 配置中心 | Nacos | 2.x | 综合节点 | 配置治理与注册管理 |
| 对象存储 | MinIO | RELEASE 稳定版 | 综合节点 | 图片、附件、导出文件存储 |
| 对象存储 | RustFS | 以项目实际版本为准 | 综合节点 | 图片、附件、导出文件存储 |
| 数据库代理 | HAProxy | 2.x | 综合节点 | 数据库读写入口代理 |
| 连接池 | PgBouncer | 1.2x+ | 综合节点 | 统一数据库连接池 |
| 高可用控制 | Patroni | 稳定版 | 综合节点 | 主备状态管理与切换 |
@ -474,7 +540,7 @@ flowchart TB
| HAProxy | 综合节点 | Docker 部署 | 是,优先建议 | 作为数据库代理入口,适合 `host` 模式 |
| PgBouncer | 综合节点 | Docker 部署 | 是,优先建议 | 作为数据库连接池入口,适合 `host` 模式 |
| Patroni | 综合节点 | 物理机/虚拟机直接部署 | 否 | 建议与系统服务集成,便于运维与切换控制 |
| MinIO | 综合节点 | Docker 部署 | 否 | 更关注数据盘挂载与对象存储目录管理 |
| RustFS | 综合节点 | Docker 部署 | 否 | 更关注数据盘挂载与对象存储目录管理 |
| PostgreSQL 主库 | 主库服务器 | 物理机/虚拟机直接部署 | 否 | 核心数据库本体不建议容器化 |
| PostgreSQL 热备 | 热备服务器 | 物理机/虚拟机直接部署 | 否 | 高可用数据库本体不建议容器化 |
@ -497,7 +563,7 @@ flowchart TB
以下组件不建议采用 `Docker + host` 模式:
1. `Spring Boot` 业务应用:应保留容器网络隔离,便于扩容和端口治理。
2. `MinIO`:应以存储挂载与数据目录管理为重点,不依赖 `host` 模式。
2. `RustFS`:应以存储挂载与数据目录管理为重点,不依赖 `host` 模式。
3. `PostgreSQL 主库 / 热备`:数据库本体优先直接部署,不建议容器化。
4. `Patroni`:建议直接部署,便于与数据库高可用控制链路协同。
@ -509,7 +575,7 @@ flowchart TB
|---|---|---|
| 公网接入区 | 公网入口薄转发 | 对外提供 HTTPS 访问,不纳入我方主机资源 |
| 应用区 | 业务应用节点 | 仅允许内网接入区与运维区访问 |
| 中间件与文件存储区 | Redis、Nacos、MinIO、数据库控制组件 | 仅允许业务应用节点与运维区访问 |
| 中间件与文件存储区 | Redis、Nacos、RustFS、数据库控制组件 | 仅允许业务应用节点与运维区访问 |
| 银行文件交换区 | SFTP/FTP 文件交换服务器 | 仅允许业务应用节点、银行专线或授权外联链路访问 |
| 数据区 | PostgreSQL 主库、热备库、备份存储 | 严格限制,仅允许中间件控制主机和运维区访问 |
@ -535,7 +601,7 @@ flowchart TB
| 对外访问 | 开通 443 端口 | 提供统一 HTTPS 入口 |
| 公网入口薄转发访问内网 Nginx | 开通公网入口到内网 Nginx 的转发端口 | 仅授权链路访问 |
| 内网 Nginx 访问应用 | 开通内网 Nginx 到业务应用的 API / 网关端口 | 仅内网访问 |
| 应用访问综合节点 | 开通 Redis、Nacos、MinIO、PgBouncer 相关端口 | 仅应用区访问 |
| 应用访问综合节点 | 开通 Redis、Nacos、RustFS、PgBouncer 相关端口 | 仅应用区访问 |
| 业务应用访问 SFTP/FTP 服务器 | 开通 SFTP/FTP 相关端口 | 用于银行文件送盘、回盘、对账交换 |
| 银行链路访问 SFTP/FTP 服务器 | 开通 FTP/SFTP 服务端口 | 仅银行授权链路访问 |
| 综合节点访问数据库 | 开通 PostgreSQL 5432 及健康检查相关端口 | 仅综合节点访问 |
@ -551,7 +617,7 @@ flowchart TB
| 业务应用节点(主) | 综合节点 | TCP/6379 | Redis 访问 | 内网放通 |
| 业务应用节点(主) | 综合节点 | TCP/8848 | Nacos 访问 | 内网放通 |
| 业务应用节点(主) | 综合节点 | TCP/6432 | PgBouncer 访问 | 内网放通 |
| 业务应用节点(主) | 综合节点 | TCP/9000,9001 | MinIO 文件访问 | 内网放通 |
| 业务应用节点(主) | 综合节点 | RustFS 对象存储端口 | RustFS 文件访问 | 内网放通 |
| 业务应用节点(主) | SFTP/FTP 文件交换服务器 | TCP/21 或 22 | 银行送盘、回盘、对账文件交换 | 内网放通 |
| 银行专线或授权外联链路 | SFTP/FTP 文件交换服务器 | TCP/21 或 22 | 银行文件目录投递与回收 | 仅授权链路放通 |
| 综合节点 | PostgreSQL 主库服务器 | TCP/5432 | 数据库代理与控制访问 | 内网放通 |
@ -569,7 +635,7 @@ flowchart TB
| Spring Boot Gateway / 业务应用端口 | 项目自定义端口 | 仅内网 Nginx 与内网调用 |
| Redis | 6379 | 仅业务应用与运维可访问 |
| Nacos | 8848 | 仅业务应用与运维可访问 |
| MinIO | 9000/9001 | 仅业务应用与运维可访问 |
| RustFS | 按 RustFS 实际部署端口 | 仅业务应用与运维可访问 |
| SFTP/FTP 服务 | 21 或 22 | 仅业务应用节点、运维和银行授权链路可访问 |
| PgBouncer | 6432 | 仅业务应用可访问 |
| HAProxy | 5000 或项目定义端口 | 仅 PgBouncer 与运维可访问 |
@ -588,7 +654,7 @@ flowchart TB
1. 安装操作系统并完成安全基线加固。
2. 在业务应用节点安装 JDK、部署业务运行环境。
3. 在内网 Nginx 入口节点安装 Nginx。
4. 在综合节点安装 Redis、Nacos、HAProxy、PgBouncer、Patroni、MinIO
4. 在综合节点安装 Redis、Nacos、RustFS、HAProxy、PgBouncer、Patroni。
5. 在 SFTP/FTP 文件交换服务器安装 SFTP/FTP 服务并配置目录结构。
6. 在数据库主备节点安装 PostgreSQL 16。
@ -604,9 +670,9 @@ flowchart TB
1. 在业务应用节点部署 Spring Boot Gateway 和业务应用服务。
2. 在内网 Nginx 入口节点配置 API 转发和内部负载均衡规则。
3. 在综合节点初始化 MinIO 存储桶和访问策略。
3. 在综合节点初始化 RustFS 存储桶和访问策略。
4. 在 SFTP/FTP 文件交换服务器配置送盘、回盘、对账、归档目录。
5. 配置业务应用到 Redis、Nacos、PgBouncer、MinIO 的连接参数。
5. 配置业务应用到 Redis、Nacos、RustFS、PgBouncer 的连接参数。
### 5. 联调与演练
@ -631,7 +697,7 @@ flowchart TB
| 业务应用可用性 | 表务、抄表、收费、账务、发票、报表等核心服务正常 | 业务主流程可执行 |
| Redis 可用性 | 缓存读写正常 | 中间件能力正常 |
| Nacos 可用性 | 配置下发正常 | 配置治理能力正常 |
| MinIO 可用性 | 图片、附件上传下载正常 | 文件存储能力正常 |
| RustFS 可用性 | 图片、附件上传下载正常 | 文件存储能力正常 |
| SFTP/FTP 文件交换 | 送盘、回盘、对账目录读写正常 | 银行文件交换能力正常 |
| 数据库连接能力 | 业务应用可通过 PgBouncer 正常连接数据库 | 代理接入正常 |
| PostgreSQL 主备同步 | 主备复制正常,无严重延迟 | 高可用基础正常 |
@ -647,7 +713,18 @@ flowchart TB
1. 公网入口薄转发不纳入我方主机资源;我方实际部署的统一接入入口为内网 Nginx 入口节点。
2. 2 台业务应用节点作为核心业务集群,节点内同时部署 Spring Boot Gateway 和业务服务,承接微服务统一接入与核心业务处理。
3. 综合节点集中承载 Redis、Nacos、MinIO 及数据库控制组件,进一步压缩一期主机数量并降低部署复杂度。
3. 综合节点集中承载 Redis、Nacos、RustFS 及数据库控制组件,进一步压缩一期主机数量并降低部署复杂度。
## RustFS 产品介绍与选型说明
RustFS 是一款支持私有化部署的 S3 兼容对象存储方案可用于承接图片、附件、导出文件和归档文件等非结构化数据场景。结合本项目当前整体部署方案RustFS 作为综合节点上的对象存储组件,可替代 MinIO 承接对象存储能力。
本项目采用 RustFS 的原因如下:
1. RustFS 具备对象存储能力,适合图片、附件、导出文件和归档文件统一存储。
2. RustFS 支持私有化部署,适合甲方对自主可控和本地化部署的要求。
3. RustFS 可作为独立对象存储组件部署在综合节点中,与缓存、配置治理和数据库控制能力协同运行。
4. 当前方案中,银行文件交换仍由独立的 SFTP/FTP 文件交换服务器承接RustFS 不承担银行送盘、回盘和对账文件交换职责。
4. 新增 1 台 SFTP/FTP 文件交换服务器,作为银行送盘、回盘、对账文件交换专用前置机。
5. PostgreSQL 16 采用同城双可用区 1 主 1 热备部署,满足高可用要求。
6. 网络采用公网接入区、内网接入区、应用区、中间件与文件存储区、银行文件交换区、数据区分层隔离模式,以满足安全性、可维护性和资源审批要求。

View File

@ -0,0 +1,419 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.6.6 Chrome/144.0.7559.236 Electron/40.8.4 Safari/537.36" version="29.6.6" pages="3">
<diagram id="zones" name="网络分区图">
<mxGraphModel grid="1" page="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" pageScale="1" pageWidth="1800" pageHeight="1000" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="9ridG9Hz4lSlouddoKVb-23" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="核心区" vertex="1">
<mxGeometry height="600" width="380" x="1060" y="-64" as="geometry" />
</mxCell>
<mxCell id="9ridG9Hz4lSlouddoKVb-22" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#eff6ff;strokeColor=#2563eb;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="办公区" vertex="1">
<mxGeometry height="178" width="200" x="140" y="-68" as="geometry" />
</mxCell>
<mxCell id="z1" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff7ed;strokeColor=#ea580c;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="Untrust&#xa;外网区域" vertex="1">
<mxGeometry height="424" width="200" x="140" y="120" as="geometry" />
</mxCell>
<mxCell id="m1" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.people.standing_man_2;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="移动端用户" vertex="1">
<mxGeometry height="70" width="40" x="230" y="135" as="geometry" />
</mxCell>
<mxCell id="m2" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.computers_and_peripherals.pc;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="第三方系统" vertex="1">
<mxGeometry height="80" width="80" x="210" y="264" as="geometry" />
</mxCell>
<mxCell id="m3" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.buildings.government_building;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="银行系统&#xa;公网/专线" vertex="1">
<mxGeometry height="80" width="80" x="210" y="367" as="geometry" />
</mxCell>
<mxCell id="z2" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fffbeb;strokeColor=#d97706;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="DMZ&#xa;对外服务区" vertex="1">
<mxGeometry height="608" width="280" x="370" y="-68" as="geometry" />
</mxCell>
<mxCell id="nginx" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.servers.www_server;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="Nginx 入口" vertex="1">
<mxGeometry height="82" width="85" x="480" y="123" as="geometry" />
</mxCell>
<mxCell id="ftp" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.servers.fileserver;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="SFTP/FTP&#xa;文件交换服务器" vertex="1">
<mxGeometry height="88" width="70" x="565" y="367" as="geometry" />
</mxCell>
<mxCell id="z3" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#eff6ff;strokeColor=#2563eb;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="服务器区域" vertex="1">
<mxGeometry height="610" width="330" x="670" y="-70" as="geometry" />
</mxCell>
<mxCell id="pc" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.computers_and_peripherals.pc;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="PC 端用户&#xa;办公网段" vertex="1">
<mxGeometry height="92" width="95" x="190" y="-20" as="geometry" />
</mxCell>
<mxCell id="svc" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.misc.hp_mini;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="综合节点&lt;br&gt;中间件&lt;div&gt;数据库存储控制&lt;/div&gt;" vertex="1">
<mxGeometry height="73.38" width="80" x="780" y="345.31" as="geometry" />
</mxCell>
<mxCell id="db1" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.storage.relational_database;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="PostgreSQL 主库" vertex="1">
<mxGeometry height="84" width="118" x="1100" y="330" as="geometry" />
</mxCell>
<mxCell id="db2" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.storage.relational_database;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="PostgreSQL 热备" vertex="1">
<mxGeometry height="84" width="118" x="1100" y="180" as="geometry" />
</mxCell>
<mxCell id="bak" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.servers.fileserver;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="备份归档存储" vertex="1">
<mxGeometry height="84" width="60" x="1360" y="180" as="geometry" />
</mxCell>
<mxCell id="e1" edge="1" parent="1" source="m1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="nginx" value="HTTPS 443">
<mxGeometry relative="1" as="geometry">
<mxPoint x="380" y="145" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="e2" edge="1" parent="1" source="m2" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" target="nginx" value="HTTPS/API">
<mxGeometry relative="1" as="geometry">
<mxPoint x="415" y="171.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="e2b" edge="1" parent="1" source="m3" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="ftp" value="公网隧道&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;/专线&lt;/span&gt;21/22 银行文件交换">
<mxGeometry relative="1" x="0.1096" y="-3" as="geometry">
<mxPoint as="offset" />
<mxPoint x="380" y="407" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="e3" edge="1" parent="1" source="pc" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="nginx" value="办公网访问,内网 IP">
<mxGeometry relative="1" as="geometry">
<mxPoint x="510" y="104" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="e4" edge="1" parent="1" source="nginx" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;" target="9ridG9Hz4lSlouddoKVb-13" value="API转发">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="560" y="124" />
<mxPoint x="560" y="130" />
<mxPoint x="694" y="130" />
</Array>
<mxPoint x="565" y="165" as="sourcePoint" />
<mxPoint x="817.3199999999999" y="256.38000000000045" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="e8" edge="1" parent="1" source="9ridG9Hz4lSlouddoKVb-13" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="svc" value="业务访问">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e10" edge="1" parent="1" source="9ridG9Hz4lSlouddoKVb-13" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;exitX=0.035;exitY=0.76;exitDx=0;exitDy=0;exitPerimeter=0;" target="ftp" value="21/22 文件交换">
<mxGeometry relative="1" as="geometry">
<mxPoint as="offset" />
<Array as="points">
<mxPoint x="703" y="210" />
<mxPoint x="600" y="210" />
</Array>
<mxPoint x="1010" y="286" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="e11" edge="1" parent="1" source="svc" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="db1" value="5432 数据库访问">
<mxGeometry relative="1" x="-0.0013" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="e12" edge="1" parent="1" source="svc" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;dashed=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" target="db2" value="5432 状态探测">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="980" y="350" />
<mxPoint x="980" y="222" />
</Array>
<mxPoint x="1160" y="446" as="sourcePoint" />
<mxPoint x="1339" y="104.00000000000023" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="e13" edge="1" parent="1" source="db1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;exitX=0.5;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;" target="db2" value="主备同步">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e14" edge="1" parent="1" source="db1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="bak" value="备份/WAL">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e15" edge="1" parent="1" source="db2" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="bak" value="备份副本">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e16" edge="1" parent="1" source="svc" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;exitX=0.9;exitY=0.9;exitDx=0;exitDy=0;exitPerimeter=0;" target="bak" value="文件归档">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="852" y="440" />
<mxPoint x="1420" y="440" />
</Array>
<mxPoint x="1130" y="468.04761904761926" as="sourcePoint" />
<mxPoint x="1487.0476190476188" y="371.99999999999955" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HN1-GFPAo3kp1Sdrea_3-7" edge="1" parent="1" source="z1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" target="z1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="app1" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.misc.hp_mini;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="业务应用节点 1&#xa;Spring Boot Gateway&#xa;业务服务" vertex="1">
<mxGeometry height="73" width="90" x="775" y="144" as="geometry" />
</mxCell>
<mxCell id="app2" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.misc.hp_mini;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="业务应用节点 2&#xa;Spring Boot Gateway&#xa;业务服务" vertex="1">
<mxGeometry height="72" width="90" x="777.5" y="-5" as="geometry" />
</mxCell>
<mxCell id="9ridG9Hz4lSlouddoKVb-13" parent="1" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;sketch=0;pointerEvents=1;strokeColor=#99CCFF;strokeWidth=2;align=center;verticalAlign=top;fontFamily=Helvetica;fontSize=12;fontColor=default;fillColor=none;perimeterSpacing=6;" value="" vertex="1">
<mxGeometry height="305" width="240" x="701.5" y="-22" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="links" name="网络连接图">
<mxGraphModel grid="1" page="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" pageScale="1" pageWidth="1800" pageHeight="1000" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="lz1" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff7ed;strokeColor=#ea580c;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="Untrust&#xa;外网区域" vertex="1">
<mxGeometry height="220" width="260" x="30" y="90" as="geometry" />
</mxCell>
<mxCell id="lm1" parent="1" style="shape=mxgraph.cisco.people.man;html=1;fillColor=#ffffff;strokeColor=#ea580c;" value="移动端用户" vertex="1">
<mxGeometry height="80" width="80" x="60" y="145" as="geometry" />
</mxCell>
<mxCell id="lm2" parent="1" style="shape=mxgraph.cisco.misc.generic_building;html=1;fillColor=#ffffff;strokeColor=#ea580c;" value="第三方系统" vertex="1">
<mxGeometry height="80" width="80" x="160" y="145" as="geometry" />
</mxCell>
<mxCell id="lm3" parent="1" style="shape=mxgraph.cisco.misc.generic_building;html=1;fillColor=#ffffff;strokeColor=#ea580c;" value="银行系统&#xa;公网/专线" vertex="1">
<mxGeometry height="80" width="110" x="95" y="230" as="geometry" />
</mxCell>
<mxCell id="ldmz" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fffbeb;strokeColor=#d97706;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="DMZ&#xa;对外服务区" vertex="1">
<mxGeometry height="250" width="300" x="340" y="70" as="geometry" />
</mxCell>
<mxCell id="lnginx" parent="1" style="shape=mxgraph.cisco.servers.server;html=1;fillColor=#ffffff;strokeColor=#d97706;" value="内网 Nginx 入口节点" vertex="1">
<mxGeometry height="82" width="105" x="435" y="118" as="geometry" />
</mxCell>
<mxCell id="lftp" parent="1" style="shape=mxgraph.cisco.servers.server;html=1;fillColor=#fff1f2;strokeColor=#dc2626;strokeWidth=2;" value="SFTP/FTP&#xa;文件交换服务器" vertex="1">
<mxGeometry height="88" width="145" x="415" y="220" as="geometry" />
</mxCell>
<mxCell id="llan" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eff6ff;strokeColor=#2563eb;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="LAN&#xa;办公与应用区" vertex="1">
<mxGeometry height="360" width="560" x="690" y="50" as="geometry" />
</mxCell>
<mxCell id="lpc" parent="1" style="shape=mxgraph.cisco.people.man;html=1;fillColor=#ffffff;strokeColor=#2563eb;" value="PC 端用户&#xa;办公网段" vertex="1">
<mxGeometry height="92" width="95" x="720" y="108" as="geometry" />
</mxCell>
<mxCell id="lsw" parent="1" style="shape=mxgraph.cisco.switches.workgroup_switch;html=1;fillColor=#ffffff;strokeColor=#2563eb;" value="应用区交换" vertex="1">
<mxGeometry height="74" width="104" x="870" y="130" as="geometry" />
</mxCell>
<mxCell id="lapp1" parent="1" style="shape=mxgraph.cisco.servers.server;html=1;fillColor=#ffffff;strokeColor=#2563eb;" value="业务应用节点 1&#xa;Spring Boot Gateway&#xa;业务服务" vertex="1">
<mxGeometry height="96" width="120" x="1010" y="102" as="geometry" />
</mxCell>
<mxCell id="lapp2" parent="1" style="shape=mxgraph.cisco.servers.server;html=1;fillColor=#ffffff;strokeColor=#2563eb;" value="业务应用节点 2&#xa;Spring Boot Gateway&#xa;业务服务" vertex="1">
<mxGeometry height="96" width="120" x="1010" y="228" as="geometry" />
</mxCell>
<mxCell id="lsvc" parent="1" style="shape=mxgraph.cisco.servers.server;html=1;fillColor=#f8f4ff;strokeColor=#7c3aed;strokeWidth=2;" value="综合节点&#xa;缓存: Redis&#xa;配置: Nacos&#xa;对象存储: MinIO&#xa;数据库控制: HAProxy / PgBouncer / Patroni" vertex="1">
<mxGeometry height="134" width="200" x="800" y="245" as="geometry" />
</mxCell>
<mxCell id="lcore" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ecfdf5;strokeColor=#059669;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="Core&#xa;核心数据区" vertex="1">
<mxGeometry height="280" width="470" x="1300" y="90" as="geometry" />
</mxCell>
<mxCell id="ldb1" parent="1" style="shape=mxgraph.cisco.servers.database;html=1;fillColor=#ffffff;strokeColor=#059669;" value="PostgreSQL 主库" vertex="1">
<mxGeometry height="84" width="118" x="1355" y="145" as="geometry" />
</mxCell>
<mxCell id="ldb2" parent="1" style="shape=mxgraph.cisco.servers.database;html=1;fillColor=#ffffff;strokeColor=#059669;" value="PostgreSQL 热备" vertex="1">
<mxGeometry height="84" width="118" x="1510" y="145" as="geometry" />
</mxCell>
<mxCell id="lbak" parent="1" style="shape=mxgraph.cisco.storage.storage_array;html=1;fillColor=#ffffff;strokeColor=#d97706;strokeWidth=2;" value="备份归档存储" vertex="1">
<mxGeometry height="84" width="170" x="1432" y="260" as="geometry" />
</mxCell>
<mxCell id="le1" edge="1" parent="1" source="lm1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lnginx" value="HTTPS 443">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le2" edge="1" parent="1" source="lm2" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lnginx" value="HTTPS/API">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le2b" edge="1" parent="1" source="lm3" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lftp" value="21/22 银行文件交换">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le3" edge="1" parent="1" source="lpc" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lnginx" value="办公网访问">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le4" edge="1" parent="1" source="lnginx" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lsw" value="API转发">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le5" edge="1" parent="1" source="lsw" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lapp1" value="节点1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le6" edge="1" parent="1" source="lsw" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lapp2" value="节点2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le7" edge="1" parent="1" source="lapp1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lsvc" value="业务访问">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le8" edge="1" parent="1" source="lapp2" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lsvc" value="业务访问">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le9" edge="1" parent="1" source="lapp1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lftp" value="21/22 文件交换">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le10" edge="1" parent="1" source="lapp2" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lftp" value="21/22 文件交换">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le11" edge="1" parent="1" source="lsvc" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="ldb1" value="5432 数据库访问">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le12" edge="1" parent="1" source="lsvc" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;dashed=1;" target="ldb2" value="5432 状态探测">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le13" edge="1" parent="1" source="ldb1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="ldb2" value="主备同步">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le14" edge="1" parent="1" source="ldb1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lbak" value="备份/WAL">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le15" edge="1" parent="1" source="ldb2" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lbak" value="备份副本">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="le16" edge="1" parent="1" source="lsvc" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="lbak" value="文件归档">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="1P_7QRTpX64gtdREb-dQ" name="讨论版本">
<mxGraphModel dx="1298" dy="853" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="cTkcAQCcS-jnWanXpuNl-1" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="内网区" vertex="1">
<mxGeometry height="610" width="470" x="920" y="480" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-2" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#eff6ff;strokeColor=#2563eb;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="办公区" vertex="1">
<mxGeometry height="178" width="200" x="140" y="482" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-3" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff7ed;strokeColor=#ea580c;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="公网区域" vertex="1">
<mxGeometry height="424" width="200" x="140" y="670" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-4" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.people.standing_man_2;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="移动端用户" vertex="1">
<mxGeometry height="70" width="40" x="230" y="699" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-5" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.computers_and_peripherals.pc;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="第三方系统" vertex="1">
<mxGeometry height="80" width="80" x="210" y="826" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-6" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" target="cTkcAQCcS-jnWanXpuNl-31">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-7" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.buildings.government_building;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="银行系统&#xa;公网/专线" vertex="1">
<mxGeometry height="80" width="80" x="210" y="956" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-8" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fffbeb;strokeColor=#d97706;strokeWidth=2;fontStyle=1;align=left;verticalAlign=top;spacingLeft=10;spacingTop=8;" value="互联网区/DMZ" vertex="1">
<mxGeometry height="608" width="520" x="370" y="482" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-9" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.servers.fileserver;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="SFTP/FTP&#xa;文件交换服务器" vertex="1">
<mxGeometry height="88" width="70" x="703.75" y="948" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-10" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.computers_and_peripherals.pc;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="PC 端用户&#xa;办公网段" vertex="1">
<mxGeometry height="92" width="95" x="190" y="530" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-11" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.misc.hp_mini;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="综合节点&lt;br&gt;&lt;br&gt;&lt;div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="73.38" width="80" x="970" y="641.81" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-12" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.storage.relational_database;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="PostgreSQL 主库" vertex="1">
<mxGeometry height="84" width="118" x="1164" y="730" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-13" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.storage.relational_database;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="PostgreSQL 热备" vertex="1">
<mxGeometry height="84" width="118" x="1164" y="547" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-14" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.servers.fileserver;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="备份归档存储" vertex="1">
<mxGeometry height="84" width="60" x="1294" y="940" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-15" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-4" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-31" value="HTTPS 443">
<mxGeometry relative="1" as="geometry">
<mxPoint x="380" y="695" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-16" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-5" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;entryX=0.12;entryY=0.9;entryDx=0;entryDy=0;entryPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-31" value="HTTPS/API">
<mxGeometry relative="1" as="geometry">
<mxPoint x="415" y="721.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-17" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-7" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="cTkcAQCcS-jnWanXpuNl-9" value="公网隧道&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;/专线&lt;/span&gt;21/22 银行文件交换">
<mxGeometry relative="1" x="0.1096" y="-3" as="geometry">
<mxPoint as="offset" />
<mxPoint x="380" y="957" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-18" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-10" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-33" value="办公网访问,内网 IP">
<mxGeometry relative="1" as="geometry">
<mxPoint x="510" y="654" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-19" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-33" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;entryX=0.038;entryY=0.681;entryDx=0;entryDy=0;entryPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-29" value="API转发">
<mxGeometry relative="1" as="geometry">
<mxPoint x="694" y="656" as="sourcePoint" />
<mxPoint x="763" y="676.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-20" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-29" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="cTkcAQCcS-jnWanXpuNl-11" value="业务访问">
<mxGeometry relative="1" as="geometry">
<mxPoint x="750.75" y="903" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-21" edge="1" parent="1" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="cTkcAQCcS-jnWanXpuNl-9" value="21/22 文件交换">
<mxGeometry relative="1" as="geometry">
<mxPoint as="offset" />
<Array as="points" />
<mxPoint x="740" y="806" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-22" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-39" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;exitX=1;exitY=0.75;exitDx=0;exitDy=0;" target="cTkcAQCcS-jnWanXpuNl-12" value="5432 数据库访问">
<mxGeometry relative="1" x="-0.0013" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-23" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-39" style="html=1;endArrow=block;dashed=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;exitX=1;exitY=0;exitDx=0;exitDy=0;edgeStyle=orthogonalEdgeStyle;" target="cTkcAQCcS-jnWanXpuNl-13" value="5432 状态探测">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1110" y="730" />
<mxPoint x="1110" y="589" />
</Array>
<mxPoint x="1011" y="863" as="sourcePoint" />
<mxPoint x="1150" y="755" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-24" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-12" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;exitX=0.5;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-13" value="主备同步">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-25" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-12" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="cTkcAQCcS-jnWanXpuNl-14" value="备份/WAL">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-26" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-13" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;" target="cTkcAQCcS-jnWanXpuNl-14" value="备份副本">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-27" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-38" style="edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;exitX=0.37;exitY=0.994;exitDx=0;exitDy=0;exitPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-14" value="文件归档">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1130" y="1018.0476190476193" as="sourcePoint" />
<mxPoint x="1487.0476190476188" y="921.9999999999995" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-28" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" target="cTkcAQCcS-jnWanXpuNl-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-29" parent="1" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;sketch=0;pointerEvents=1;strokeColor=#99CCFF;strokeWidth=2;align=center;verticalAlign=top;fontFamily=Helvetica;fontSize=12;fontColor=default;fillColor=none;perimeterSpacing=6;" value="" vertex="1">
<mxGeometry height="305" width="171.5" x="640" y="526" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-30" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.misc.hp_mini;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="业务应用节点 2&#xa;Spring Boot Gateway&#xa;业务服务" vertex="1">
<mxGeometry height="72" width="90" x="675.75" y="553" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-31" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.routers.router;" value="边界路由 NAT 转发" vertex="1">
<mxGeometry height="53" width="78" x="400" y="709" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-32" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.13;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-33">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-33" parent="1" style="strokeColor=#ffffff;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.servers.www_server;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="Nginx 入口" vertex="1">
<mxGeometry height="82" width="85" x="500" y="693" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-34" parent="1" style="sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.cisco.misc.hp_mini;fontFamily=Helvetica;fontSize=12;fontColor=default;" value="业务应用节点 1&#xa;Spring Boot Gateway&#xa;业务服务" vertex="1">
<mxGeometry height="73" width="90" x="680.75" y="698.5" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-35" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-36" connectable="0" parent="1" style="group" value="" vertex="1">
<mxGeometry height="90" width="84" x="966" y="750" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-37" parent="cTkcAQCcS-jnWanXpuNl-36" style="text;html=1;whiteSpace=wrap;strokeColor=default;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="中间件" vertex="1">
<mxGeometry height="30" width="84" y="30" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-38" parent="cTkcAQCcS-jnWanXpuNl-36" style="text;html=1;whiteSpace=wrap;strokeColor=default;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="对象存储" vertex="1">
<mxGeometry height="30" width="84" y="60" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-39" parent="cTkcAQCcS-jnWanXpuNl-36" style="text;html=1;whiteSpace=wrap;strokeColor=default;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;数据库管理控件&lt;/span&gt;" vertex="1">
<mxGeometry height="30" width="84" as="geometry" />
</mxCell>
<mxCell id="cTkcAQCcS-jnWanXpuNl-40" edge="1" parent="1" source="cTkcAQCcS-jnWanXpuNl-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;" target="cTkcAQCcS-jnWanXpuNl-31" value="HTTPS/API">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="290" y="960" />
<mxPoint x="439" y="960" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,74 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PlanB Network Security Zones</title>
<style>
body { margin: 0; padding: 24px; background: #f5f7fb; color: #0f172a; font: 14px/1.5 "PingFang SC","Microsoft YaHei",sans-serif; }
h1 { margin: 0 0 8px; font-size: 22px; }
p { margin: 0 0 16px; color: #475569; }
.card { background: #fff; border: 1px solid #dbe3ef; border-radius: 16px; padding: 16px; box-shadow: 0 10px 24px rgba(15,23,42,.06); }
canvas { width: 100%; height: auto; display: block; background: #fff; border-radius: 12px; }
</style>
</head>
<body>
<h1>福建水务营收系统网络安全域图</h1>
<p>按“互联网区DMZ/ 非互联网区”两大安全域重绘,仅保留应用系统相关对象。防火墙与路由器仅做抽象表达。</p>
<div class="card">
<canvas id="c" width="1800" height="1100"></canvas>
</div>
<script>
const C = {
ink:"#0f172a", line:"#5b9bd5", zone:"#f8fafc", zoneBorder:"#94a3b8",
dmz:"#fff7ed", dmzBorder:"#ea580c", inner:"#eff6ff", innerBorder:"#2563eb",
svc:"#f5f3ff", svcBorder:"#7c3aed", data:"#ecfdf5", dataBorder:"#059669",
bank:"#fef2f2", bankBorder:"#dc2626", backup:"#fffbeb", backupBorder:"#d97706"
};
function rr(ctx,x,y,w,h,r,fill,stroke,lw=2){ctx.beginPath();ctx.moveTo(x+r,y);ctx.arcTo(x+w,y,x+w,y+h,r);ctx.arcTo(x+w,y+h,x,y+h,r);ctx.arcTo(x,y+h,x,y,r);ctx.arcTo(x,y,x+w,y,r);ctx.closePath();ctx.fillStyle=fill;ctx.fill();ctx.lineWidth=lw;ctx.strokeStyle=stroke;ctx.stroke();}
function txt(ctx,lines,x,y,opt={}){const a=Array.isArray(lines)?lines:[lines],s=opt.size||16,w=opt.weight||"600";ctx.fillStyle=opt.color||C.ink;ctx.font=`${w} ${s}px "PingFang SC","Microsoft YaHei",sans-serif`;ctx.textAlign=opt.align||"center";ctx.textBaseline="middle";a.forEach((l,i)=>ctx.fillText(l,x,y+i*(s+5)));}
function box(ctx,x,y,w,h,lines,fill,stroke,size=15){rr(ctx,x,y,w,h,10,fill||"#fff",stroke||C.line,2);txt(ctx,lines,x+w/2,y+h/2-(Array.isArray(lines)?8:0),{size});}
function arrow(ctx,x1,y1,x2,y2,label=""){ctx.beginPath();ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);ctx.lineWidth=2;ctx.strokeStyle=C.line;ctx.stroke();const a=Math.atan2(y2-y1,x2-x1),l=10;ctx.beginPath();ctx.moveTo(x2,y2);ctx.lineTo(x2-l*Math.cos(a-Math.PI/6),y2-l*Math.sin(a-Math.PI/6));ctx.lineTo(x2-l*Math.cos(a+Math.PI/6),y2-l*Math.sin(a+Math.PI/6));ctx.closePath();ctx.fillStyle=C.line;ctx.fill();if(label){rr(ctx,(x1+x2)/2-90,(y1+y2)/2-28,180,28,8,"#fff","#cbd5e1",1);txt(ctx,label,(x1+x2)/2,(y1+y2)/2-14,{size:12,weight:"500",color:"#475569"});}}
const c=document.getElementById("c"),ctx=c.getContext("2d");
// DMZ
rr(ctx,40,40,520,980,28,C.dmz,C.dmzBorder);
txt(ctx,"互联网区DMZ",300,72,{size:24});
box(ctx,90,120,140,56,"移动端用户","#fff",C.dmzBorder,15);
box(ctx,260,120,140,56,"第三方系统","#fff",C.dmzBorder,15);
box(ctx,155,220,180,64,["公网接入代理","外部设施"],"#fff",C.dmzBorder,15);
box(ctx,155,350,180,64,["SFTP / FTP","文件交换服务器"],"#fff",C.bankBorder,15);
box(ctx,155,500,180,64,["边界防火墙","/ 路由设备"],"#fff",C.dmzBorder,15);
txt(ctx,["说明DMZ 中仅保留", "公网接入代理与银行文件交换服务"],300,650,{size:15,weight:"500",color:"#475569"});
// non-internet
rr(ctx,620,40,1140,980,28,C.inner,C.innerBorder);
txt(ctx,"非互联网区",1190,72,{size:24});
box(ctx,690,120,200,64,["办公网段", "PC 端用户"],"#fff",C.innerBorder,15);
box(ctx,1010,120,220,64,["内网 Nginx", "机房接入入口"],"#fff",C.innerBorder,15);
box(ctx,1360,120,220,64,["业务应用集群", "Gateway + 业务服务"],"#fff",C.innerBorder,15);
box(ctx,980,320,280,74,["综合节点", "Redis / Nacos / MinIO", "HAProxy / PgBouncer / Patroni"],"#fff",C.svcBorder,14);
box(ctx,1360,330,180,64,["PostgreSQL", "主库"],"#fff",C.dataBorder,15);
box(ctx,1360,430,180,64,["PostgreSQL", "热备"],"#fff",C.dataBorder,15);
box(ctx,1360,560,220,74,["备份归档存储"],"#fff",C.backupBorder,16);
txt(ctx,["说明:非互联网区内承载", "内网接入、应用、综合服务、数据库与备份"],1170,760,{size:15,weight:"500",color:"#475569"});
// links
arrow(ctx,230,148,245,220,"HTTPS");
arrow(ctx,400,148,245,220,"接口");
arrow(ctx,245,284,245,350,"文件交换");
arrow(ctx,335,252,1120,152,"跨边界转发");
arrow(ctx,335,532,1120,152,"受控访问");
arrow(ctx,790,152,1010,152,"办公网访问");
arrow(ctx,1230,152,1360,152,"网关/API");
arrow(ctx,1450,184,1120,320,"业务访问");
arrow(ctx,1450,184,245,350,"21/22");
arrow(ctx,1260,357,1360,362,"5432");
arrow(ctx,1260,357,1360,462,"状态探测");
arrow(ctx,1450,394,1450,430,"主备同步");
arrow(ctx,1540,394,1540,560,"备份/WAL");
arrow(ctx,1540,494,1540,560,"备份副本");
arrow(ctx,1260,394,1360,597,"对象/文件归档");
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

View File

@ -0,0 +1,163 @@
#!/usr/bin/env python3
"""
正式网络图生成脚本
用途
- 生成 PlanB 当前正式口径下的网络分区图与网络连接图
- 作为 output/diagrams/ 下正式产物的唯一来源
说明
- 如需试验不同布局请使用 scripts/generate_planb_diagrams_variants.py
"""
from pathlib import Path
from diagrams import Cluster, Diagram, Edge
from diagrams.generic.network import Router, Switch
from diagrams.onprem.compute import Server
from diagrams.onprem.network import HAProxy, Internet, Nginx
from diagrams.onprem.storage import Ceph
ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "output" / "diagrams"
OUT.mkdir(parents=True, exist_ok=True)
GRAPH_ATTR = {
"fontsize": "20",
"bgcolor": "white",
"pad": "0.2",
"ranksep": "0.55",
"nodesep": "0.35",
"splines": "ortho",
"labelloc": "t",
"fontname": "PingFang SC",
"margin": "0.15",
"rankdir": "LR",
"newrank": "true",
}
NODE_ATTR = {
"fontname": "PingFang SC",
"fontsize": "13",
}
EDGE_ATTR = {
"fontname": "PingFang SC",
"fontsize": "11",
}
def zone_diagram():
with Diagram(
"PlanB Network Zones",
filename=str(OUT / "planb_network_zones"),
outformat="png",
show=False,
graph_attr=GRAPH_ATTR,
node_attr=NODE_ATTR,
edge_attr=EDGE_ATTR,
):
with Cluster("Untrust\n外网区域", graph_attr={"style": "rounded,filled", "color": "#ea580c", "fillcolor": "#fff7ed"}):
mobile = Internet("移动端用户")
third = Internet("第三方系统")
with Cluster("DMZ\n对外服务区", graph_attr={"style": "rounded,filled", "color": "#d97706", "fillcolor": "#fffbeb"}):
nginx_entry = Nginx("Nginx 入口")
ftp_host = Server("SFTP/FTP 文件交换服务器")
with Cluster("LAN\n办公与应用区", graph_attr={"style": "rounded,filled", "color": "#2563eb", "fillcolor": "#eff6ff"}):
office_pc = Server("PC 端用户\n办公网段")
app_sw = Switch("应用区交换")
app_cluster = Server("业务应用集群\n2 节点")
svc_host = Server("综合节点")
with Cluster("Core\n核心数据区", graph_attr={"style": "rounded,filled", "color": "#059669", "fillcolor": "#ecfdf5"}):
db_primary = Server("PostgreSQL 主库")
db_standby = Server("PostgreSQL 热备")
backup = Ceph("备份归档存储")
# enforce left-to-right zone order and keep the zone centers aligned
mobile - Edge(style="invis", weight="10") - nginx_entry
nginx_entry - Edge(style="invis", weight="10") - office_pc
office_pc - Edge(style="invis", weight="10") - db_primary
mobile >> Edge(label="HTTPS 443") >> nginx_entry
third >> Edge(label="HTTPS / API") >> nginx_entry
office_pc >> Edge(label="办公网访问") >> nginx_entry
nginx_entry >> app_sw >> app_cluster
app_cluster >> svc_host
app_cluster >> Edge(label="文件交换 21/22") >> ftp_host
svc_host >> Edge(label="数据库访问") >> db_primary
svc_host >> Edge(label="探测/控制") >> db_standby
db_primary >> Edge(label="主备同步") >> db_standby
db_primary >> Edge(label="备份/WAL") >> backup
db_standby >> Edge(label="备份副本") >> backup
svc_host >> Edge(label="文件归档") >> backup
def link_diagram():
graph_attr = dict(GRAPH_ATTR)
graph_attr["ranksep"] = "0.75"
graph_attr["nodesep"] = "0.3"
with Diagram(
"PlanB Network Links",
filename=str(OUT / "planb_network_links"),
outformat="png",
show=False,
graph_attr=graph_attr,
node_attr=NODE_ATTR,
edge_attr=EDGE_ATTR,
):
with Cluster("Untrust\n外网区域", graph_attr={"style": "rounded,filled", "color": "#ea580c", "fillcolor": "#fff7ed"}):
mobile = Internet("移动端用户")
third = Internet("第三方系统")
bank_net = Internet("银行系统\n公网/专线")
with Cluster("DMZ\n对外服务区", graph_attr={"style": "rounded,filled", "color": "#d97706", "fillcolor": "#fffbeb"}):
nginx_entry = Nginx("Nginx 入口")
bank = Server("SFTP/FTP 文件交换服务器")
with Cluster("LAN\n办公与应用区", graph_attr={"style": "rounded,filled", "color": "#2563eb", "fillcolor": "#eff6ff"}):
pc = Server("PC 端用户\n办公网段")
app_switch = Switch("应用区交换")
app1 = Server("业务应用节点 1\nGateway + Biz")
app2 = Server("业务应用节点 2\nGateway + Biz")
svc = Server("综合节点")
haproxy = HAProxy("HAProxy / PgBouncer / Patroni")
with Cluster("Core\n核心数据区", graph_attr={"style": "rounded,filled", "color": "#059669", "fillcolor": "#ecfdf5"}):
dbm = Server("PostgreSQL 主库")
dbs = Server("PostgreSQL 热备")
backup = Ceph("备份归档存储")
# enforce left-to-right zone order: Untrust -> DMZ -> LAN -> Core
mobile - Edge(style="invis", weight="10") - nginx_entry
nginx_entry - Edge(style="invis", weight="10") - pc
pc - Edge(style="invis", weight="10") - dbm
mobile >> Edge(label="HTTPS 443") >> nginx_entry
third >> Edge(label="HTTPS / 接口") >> nginx_entry
bank_net >> Edge(label="21/22") >> bank
pc >> Edge(label="办公网访问") >> nginx_entry
nginx_entry >> app_switch
app_switch >> Edge(label="Gateway / API") >> app1
app_switch >> Edge(label="Gateway / API") >> app2
app_switch >> Edge(label="业务访问") >> svc
app_switch >> Edge(label="文件交换 21/22") >> bank
svc >> Edge(label="缓存 / 配置 / 文件") >> haproxy
haproxy >> Edge(label="5432 写流量") >> dbm
haproxy >> Edge(label="5432 状态探测", style="dashed") >> dbs
dbm >> Edge(label="主备同步") >> dbs
svc >> Edge(label="文件归档") >> backup
dbm >> Edge(label="WAL / 备份") >> backup
dbs >> Edge(label="备份副本") >> backup
if __name__ == "__main__":
zone_diagram()
link_diagram()
print(OUT / "planb_network_zones.png")
print(OUT / "planb_network_links.png")

View File

@ -0,0 +1,131 @@
#!/usr/bin/env python3
"""
试验版布局脚本
用途
- 仅用于对比不同 diagrams / graphviz 布局参数的效果
- 不作为正式交付图的唯一来源
正式图来源
- scripts/generate_planb_diagrams.py
"""
from pathlib import Path
from diagrams import Cluster, Diagram, Edge
from diagrams.generic.network import Switch
from diagrams.onprem.compute import Server
from diagrams.onprem.network import HAProxy, Internet, Nginx
from diagrams.onprem.storage import Ceph
ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "output" / "diagrams_variants"
OUT.mkdir(parents=True, exist_ok=True)
BASE_GRAPH_ATTR = {
"fontsize": "20",
"bgcolor": "white",
"pad": "0.18",
"ranksep": "0.65",
"nodesep": "0.35",
"splines": "ortho",
"labelloc": "t",
"fontname": "PingFang SC",
"margin": "0.12",
"newrank": "true",
}
NODE_ATTR = {
"fontname": "PingFang SC",
"fontsize": "13",
}
EDGE_ATTR = {
"fontname": "PingFang SC",
"fontsize": "11",
}
ZONE_STYLE = {
"Untrust": {"style": "rounded,filled", "color": "#ea580c", "fillcolor": "#fff7ed"},
"DMZ": {"style": "rounded,filled", "color": "#d97706", "fillcolor": "#fffbeb"},
"LAN": {"style": "rounded,filled", "color": "#2563eb", "fillcolor": "#eff6ff"},
"Core": {"style": "rounded,filled", "color": "#059669", "fillcolor": "#ecfdf5"},
}
def build_nodes():
with Cluster("Untrust\n外网区域", graph_attr=ZONE_STYLE["Untrust"]):
mobile = Internet("移动端用户")
third = Internet("第三方系统")
bank_net = Internet("银行系统\n公网/专线")
with Cluster("DMZ\n对外服务区", graph_attr=ZONE_STYLE["DMZ"]):
nginx_entry = Nginx("Nginx 入口")
bank = Server("SFTP/FTP 文件交换服务器")
with Cluster("LAN\n办公与应用区", graph_attr=ZONE_STYLE["LAN"]):
pc = Server("PC 端用户\n办公网段")
app_switch = Switch("应用区交换")
app1 = Server("业务应用节点 1\nGateway + Biz")
app2 = Server("业务应用节点 2\nGateway + Biz")
svc = Server("综合节点")
ctrl = HAProxy("HAProxy / PgBouncer / Patroni")
with Cluster("Core\n核心数据区", graph_attr=ZONE_STYLE["Core"]):
dbm = Server("PostgreSQL 主库")
dbs = Server("PostgreSQL 热备")
backup = Ceph("备份归档存储")
return mobile, third, bank_net, nginx_entry, bank, pc, app_switch, app1, app2, svc, ctrl, dbm, dbs, backup
def wire(nodes):
mobile, third, bank_net, nginx_entry, bank, pc, app_switch, app1, app2, svc, ctrl, dbm, dbs, backup = nodes
mobile >> Edge(label="HTTPS 443") >> nginx_entry
third >> Edge(label="HTTPS / 接口") >> nginx_entry
bank_net >> Edge(label="21/22") >> bank
pc >> Edge(label="办公网访问") >> nginx_entry
nginx_entry >> app_switch
app_switch >> Edge(label="Gateway / API") >> app1
app_switch >> Edge(label="Gateway / API") >> app2
app_switch >> Edge(label="文件交换 21/22") >> bank
app_switch >> Edge(label="业务访问") >> svc
svc >> Edge(label="缓存 / 配置 / 文件") >> ctrl
ctrl >> Edge(label="5432 写流量") >> dbm
ctrl >> Edge(label="5432 状态探测", style="dashed") >> dbs
dbm >> Edge(label="主备同步") >> dbs
svc >> Edge(label="文件归档") >> backup
dbm >> Edge(label="WAL / 备份") >> backup
dbs >> Edge(label="备份副本") >> backup
def make_variant(name: str, rankdir: str, ranksep: str, nodesep: str):
graph_attr = dict(BASE_GRAPH_ATTR)
graph_attr["rankdir"] = rankdir
graph_attr["ranksep"] = ranksep
graph_attr["nodesep"] = nodesep
with Diagram(
f"PlanB {name}",
filename=str(OUT / name),
outformat="png",
show=False,
graph_attr=graph_attr,
node_attr=NODE_ATTR,
edge_attr=EDGE_ATTR,
):
nodes = build_nodes()
wire(nodes)
if __name__ == "__main__":
variants = [
("planb_links_lr_compact", "LR", "0.65", "0.30"),
("planb_links_lr_balanced", "LR", "0.9", "0.45"),
("planb_links_tb_compact", "TB", "0.75", "0.35"),
("planb_links_tb_balanced", "TB", "1.0", "0.45"),
]
for name, rankdir, ranksep, nodesep in variants:
make_variant(name, rankdir, ranksep, nodesep)
print(OUT / f"{name}.png")