BeeX 架构与部署 · 对齐稿
一、两个维度:国家 × 环境
BeeX 按 国家(country) 和 环境(env) 两个维度切分,域名约定 {服务}-{国家}-{环境}.beexofficial.com。每个格子是一套独立的栈。
| test | prod | |
|---|---|---|
| 印尼 ID | id-test 已上线 | id 待上线 |
| 马来 MY | my-test 规划中 | my 规划中 |
二、单套栈架构图(以 id-test 为例)
全部组件在 Jakarta(ap-southeast-5)。C 端走 CDN+core API,运营走 admin 前端+admin 后端;core 与 admin 后端是两台独立 ECS,但共用同一套 id-test 库。
图 1 · id-test 单套栈
flowchart TB
subgraph U["用户侧"]
direction LR
H5B["浏览器 H5"]
APP["Flutter App
WebView 载 H5
离线包 / 在线"]
OPS["运营 / 管理员"]
end
subgraph EDGE["CDN / OSS · 静态资源"]
direction LR
H5CDN["h5-id-test
OSS: beex-id-test-h5"]
ADCDN["admin-id-test
React · 一套按 env 切换"]
end
subgraph JKT["ECS + 数据 · Jakarta ap-southeast-5"]
CORE["core 服务
api-id-test · :7002"]
ADBE["admin 后端
admin-api-id-test · :7003"]
DB[("MySQL RDS
seahub_x_id_test")]
RDS[("Redis")]
end
H5B --> H5CDN
APP --> H5CDN
OPS --> ADCDN
H5B -->|"API (HTTPS)"| CORE
APP -->|"API (HTTPS)"| CORE
ADCDN -->|"API"| ADBE
ADBE -->|"提现审批代理
X-ADMIN-TOKEN"| CORE
CORE --> DB
CORE --> RDS
ADBE --> DB
classDef store fill:#fff7d6,stroke:#e6c200;
class DB,RDS store;
已核实admin 后端 health 实测 db id-test0 + redis 都 UP,且我的 admin 接口能读到 core 建表/种子的
rebate_fund_config → 两服务确为同一套库。建表/种子在服务启动时 @PostConstruct 自动跑。三、组件清单(均已核实)
| 组件 | 仓库 | 技术 | 跑在哪 | 域名 | 部署 |
|---|---|---|---|---|---|
| H5(C端) | beex-app-h5 | Nuxt3 静态 | OSS+CDN | h5-id-test | 云效 4987658 → OSS/CDN |
| 原生 App | seahub-x-app | Flutter | 应用商店 | — | WebView 载 H5(离线包从 OSS / 在线 CDN) |
| core 服务 | seahub-x-service | Spring Boot :7002 | ECS #1 | api-id-test | 云效 4914249 · VMDeploy(push 自动) |
| admin 前端 | seahub-x-admin | React/Vite 静态 | OSS+CDN | admin-id-test | 云效 4938728 → OSS/CDN(push 自动) |
| admin 后端 | seahub-x-service (admin-bootstrap) | Spring Boot :7003 | ECS #2 独立 | admin-api-id-test | 云效 5018487(今天新建 · ssh 发 jar) |
| 数据 | — | MySQL RDS + Redis | Jakarta | — | 服务启动自动建表 |
四、CI/CD 流水线(云效 Yunxiao)
源码 GitHub(chaokongzwp),企业 ID 69f064d1…。5 条流水线对应不同部署目标:静态走 OSS/CDN、core 走 VMDeploy 机器组、admin 后端走 ssh 发 jar。
图 2 · 流水线 → 部署目标
flowchart LR
subgraph GH["GitHub"]
R1["beex-app-h5"]
R2["seahub-x-service"]
R3["seahub-x-admin"]
end
subgraph YX["云效流水线"]
P2["4987658
h5 OSS/CDN"]
P1["4914249
core · VMDeploy"]
P3["4938728
admin 前端"]
P4["5018487
admin 后端 · ssh"]
end
subgraph TGT["部署目标"]
T1["OSS+CDN
h5-id-test"]
T2["ECS#1
api-id-test"]
T3["OSS+CDN
admin-id-test"]
T4["ECS#2
admin-api-id-test"]
end
R1 --> P2 --> T1
R2 --> P1 --> T2
R3 --> P3 --> T3
R2 --> P4 --> T4
两点待清理(admin 后端那条)① ECS 密码当前内联在流水线 YAML(明文)→ 建议挪进加密变量组;② API 新建的流水线 GitHub webhook 未自动装 → push 暂不自动触发,需控制台「流水线源」重存一次。
五、提现请求时序(端到端)
提现审批:H5 申请 → core 冻结余额 → 运营在 admin 审批(经 admin 后端代理,带 X-ADMIN-TOKEN 调 core)→ core 发起 Xendit 出款 → Xendit 回调结算。
图 3 · 提现时序
sequenceDiagram
autonumber
participant U as 用户 (H5)
participant C as core 服务
participant A as admin 后端
participant X as Xendit
U->>C: 申请提现 apply(选银行/钱包账户)
C->>C: 冻结余额, 状态 REQUESTED
A->>C: 审批通过 approve (X-ADMIN-TOKEN)
C->>X: 发起出款 disbursement
C-->>A: 状态 PROCESSING
X-->>C: 回调 webhook (COMPLETED / FAILED)
C->>C: 成功→扣冻结·PAID / 失败→解冻退回·FAILED
六、多国家架构 —— 已定:A 独立栈
✅ 已拍板(2026-06-05)一个国家 = 一套独立 ECS + DB + Redis,硬隔离、互不干扰(路线 A)。admin 前端是一套,靠 env 切换按钮决定后面走哪个国家的后端(一对多前端 → 各国独立后端)。第一阶段做印尼,马来为未来规划,接 MY 时复制一套独立栈即可。下面 A/B 对比保留作背景参考。
路线 A · 每国一套独立栈
按域名约定推断的方向:复制一套栈,独立库(ID 数据与 MY 数据物理隔离,利于数据合规),admin 前端复用一套(已有 env 切换器)。
图 4 · 路线 A(独立栈)
flowchart TB ADFE["admin 前端(一套)
env 切换器: id-test / id / my-test / my"] subgraph IDS["印尼栈 · Jakarta"] IDBE["core + admin 后端
api-id-test / admin-api-id-test"] IDDB[("seahub_x_id_test")] end subgraph MYS["马来栈 · 新加坡/吉隆坡"] MYBE["core + admin 后端
api-my-test / admin-api-my-test"] MYDB[("seahub_x_my_test")] end ADFE -.->|切 ID| IDBE ADFE -.->|切 MY| MYBE IDBE --> IDDB MYBE --> MYDB classDef store fill:#fff7d6,stroke:#e6c200; class IDDB,MYDB store;
路线 B · 一套后端多国共服(country_code 区分)
同一套服务 + 同一个库,按 country_code 区分。现状种子已同时塞 ID+MY 两国数据,说明代码本就按 B 写的;但 ID/MY 数据同库,印尼数据本地化合规可能有问题。
图 5 · 路线 B(单后端 country_code)
flowchart TB
ADFE["admin 前端"]
subgraph ONE["一套后端"]
BE["core + admin 后端"]
DB[("一个库
ID + MY 同库
按 country_code 区分")]
end
ADFE --> BE
BE --> DB
classDef store fill:#fff7d6,stroke:#e6c200;
class DB store;
A 独立栈
✓ 数据物理隔离(合规友好)
✓ 故障/容量互不影响
✗ 运维成本翻倍(多套 ECS/DB/流水线)
✓ 数据物理隔离(合规友好)
✓ 故障/容量互不影响
✗ 运维成本翻倍(多套 ECS/DB/流水线)
B 单后端
✓ 运维成本低、代码现成
✗ ID/MY 同库,合规风险
✗ 单点影响多国
✓ 运维成本低、代码现成
✗ ID/MY 同库,合规风险
✗ 单点影响多国
结论(已定):走 A。决定因素是合规(碰钱+实名,印尼/马来数据本地化)与故障隔离。关键澄清:A ≠ 重写代码 —— 同一套代码部署多次 + 每国独立库,代价是运维(多套 ECS/DB),不是开发。接 MY 是选 A 最便宜的时机(MY 库空,零迁移)。
七、待对齐的决策清单
| # | 问题 | 现状 | 需决定 |
|---|---|---|---|
| 1 | MY 走 A(独立栈)还是 B(单后端 country_code) | 已定:A 一国一套 ECS/DB/Redis 隔离 | —— 已拍板 |
| 2 | admin 鉴权(前端一套按 env 切换,门必须在后端) | 现状:零鉴权·公网裸奔(实测外网可读用户 PII) | 已定方向:飞书 SSO + 后端 RBAC · 开发阶段暂缓,接真实用户/上 prod 前必补 |
| 3 | admin 后端 ssh 部署 + 密码内联 | 新建流水线临时方案 | 挪进加密变量组 / 改 VMDeploy |
| 4 | admin 后端 ECS 与 core 分离 | 两台独立 ECS,同库 | 是否合并 / 是否同区 |