# 多服务部署
xly 不是单个 Spring Boot WAR。仓库包含多个可部署模块,以及一些也被 `xlyEntry` 作为依赖使用的类库型模块。
## 拓扑总览
```mermaid
flowchart LR
classDef library fill:#f5f5f5,stroke:#999,stroke-dasharray:3 3
classDef boot fill:#e8f0fe,stroke:#4285f4
subgraph clients [面向操作人员]
BACK["BACK SPA
http://<host>:8597"]
FROUNT["FROUNT SPA
http://<host>:8598"]
end
EXT([外部集成方])
HOOKS([第三方 webhook])
subgraph boots [可部署 Spring Boot 应用]
direction TB
XENTRY["xlyEntry
:8080 /xlyEntry
EntryApplicationBoot"]:::boot
XAPI["xlyApi
:8090 (local) / :8080
/xlyApi · ApiApplicationBoot"]:::boot
XIF["xlyInterface
:8080 /xlyInterface
InterfaceApplicationBoot"]:::boot
XPLC["xlyPlc
:8000 (dev) / :8080
/xlyEntry · PlcApplicationBoot"]:::boot
XFACE["xlyFace
:8091 (local) / :8080
/xlyFace(文档范围外)"]:::boot
XEJMSC["xlyErpJmsConsumer
(无端口;继承配置)
JmsConsumerApplicationBoot"]:::boot
end
subgraph libs [类库模块:不独立运行]
direction TB
XMANAGE[xlyManage]:::library
XBSERVICE[xlyBusinessService]:::library
XPERSIST[xlyPersist]:::library
XENTITY[xlyEntity]:::library
XFLOW[xlyFlow]:::library
XMSG[xlyMsg]:::library
XEJMSP[xlyErpJmsProductor]:::library
XPLATC[xlyPlatConstant]:::library
end
subgraph infra [共享基础设施]
DB[("MySQL
xlyweberp_*")]
REDIS[(Redis :16379
共享缓存 + session)]
AMQ([ActiveMQ :61616])
MONGO[("MongoDB
已接线但未使用")]
end
BACK -->|nginx| XENTRY
FROUNT -->|nginx| XENTRY
FROUNT -->|nginx| XAPI
EXT --> XAPI
HOOKS --> XIF
XENTRY --- XMANAGE
XENTRY --- XBSERVICE
XENTRY --- XFLOW
XBSERVICE --- XPERSIST
XAPI --- XPERSIST
XIF --- XPERSIST
XPERSIST --- XPLATC
XPERSIST --- XENTITY
XBSERVICE --- XMSG
XIF --- XMSG
XBSERVICE --- XEJMSP
XENTRY --> DB
XAPI --> DB
XIF --> DB
XPLC --> DB
XFLOW --> DB
XENTRY --> REDIS
XAPI --> REDIS
XEJMSC --> AMQ
XEJMSP -. 发布 .-> AMQ
XENTRY -. 发布 .-> AMQ
```
反向代理把面向操作人员的端口(8597 / 8598)映射到内部 Spring Boot 应用(大多是 `:8080`,再通过不同 context path 区分)。类库模块不会独立运行,而是作为依赖打进可部署 WAR。`xlyFlow` 和 `xlyPlc` 都共享 xlyEntry 的 context-path `/xlyEntry`,所以真实部署需要按 host 或 upstream 路由,而不能只靠 path 区分。
## 主要模块
### 可部署的 Spring Boot 应用
| 服务 / 模块 | 角色 | 默认 profile / 端口 | Boot 类 |
|---|---|---|---|
| **xlyEntry** | 主运行时与配置 / 管理接口面。承载 `/business/*`、`/gdsmodule/*`、`/gdsconfigform/*`、`/gdsconfigtb/*`、报表、登录和其他框架 controller。 | `dev` → 8080,context `/xlyEntry` | `EntryApplicationBoot` |
| **xlyApi** | 面向 `/api/*`、`/online/*`、`/pro/*`、`/thirdparty/*` 等端点的 API 模块。 | repo 默认 `local` → 8090,dev/win/linux → 8080,context `/xlyApi` | `ApiApplicationBoot` |
| **xlyInterface** | 外部集成模块,带 Swagger 依赖和第三方集成代码。 | `dev` → 8080,context `/xlyInterface` | `InterfaceApplicationBoot` |
| **xlyPlc** | 车间 PLC 桥接([切片 6](../../slices/06-hardware.md))。 | `dev` → 8000;命名 profile(15S、S10、T0、T1、CT、yt、pro)→ 8080,context `/xlyEntry`(与 xlyEntry 共享 context-path) | `PlcApplicationBoot` |
| **xlyFace** | 人脸识别模块。在 build 中(`settings.gradle` 仍按用户设置启用),但**不属于本 Wiki 文档范围**。 | repo 默认 `win` → 8080,local → 8091,context `/xlyFace` | `XlyFaceApplicationBoot` |
| **xlyErpJmsConsumer** | JMS consumer 后台服务。有 Boot main,但没有自己的 `application*.yml`;运行配置从同类服务继承。 | n/a(继承) | `JmsConsumerApplicationBoot` |
### 类库模块(在 `settings.gradle` 中启用,但不独立运行)
| 模块 | 角色 |
|---|---|
| **xlyManage** | 后台元数据管理服务(`Gds*ServiceImpl` 家族),被 xlyEntry 拉入。 |
| **xlyBusinessService** | 业务逻辑 service 层(`BusinessBaseServiceImpl` 和约 100 个兄弟 `*ServiceImpl` 类),被 xlyEntry 拉入。 |
| **xlyFlow** | 工作流 / Activiti 代码。当前分支 `XlyFlowApplicationBoot.java` 已完全注释掉;作为类库被 xlyEntry 使用。也共享 context-path `/xlyEntry`。 |
| **xlyEntity** | 共享实体 / DTO 类(约 83 个 Java 文件,包括 22 个 Mongo `@Document` 类)。 |
| **xlyPersist** | 持久化 helper(DAO、MyBatis mapper XML、`RequestAddParamUtil` 等)。 |
| **xlyMsg** | 通知 helper(钉钉、微信、邮件);没有 Boot main。 |
| **xlyErpJmsProductor** | JMS producer 代码(队列声明在 `P2pQueue.java`);没有 Boot main。 |
| **xlyPlatConstant** | 共享工具常量(`MultiThreadServer`、`TimeContant`),被 `xlyPersist` 消费。唯一仍启用的 Plat* 模块。 |
每个可运行模块有自己的 `application.yml` 和多个 `application-.yml`。启动时通过 `-Dspring.profiles.active=...` 选择 profile。
## `settings.gradle` 中禁用的模块
cleanup 分支注释掉了 17 条 `include`。其中三个是磁盘上存在的非 Plat 模块:
- `xlyErpTask`:长运行后台任务。
- `xlyRxtx`:原生串口库。xlyPlc 需要直接串口访问时可能重新启用;部分机型使用 TCP / Ethernet。
- `xlyFile`:旧文件管理模块,已被 `xlyPlatFileUpload`(也被注释)取代。
其余 14 条被注释的 include 是 `xlyTestService`、`xlyTestController`,以及除 `xlyPlatConstant` 外的完整 `xlyPlat*` 家族:`xlyPlatTask`、`xlyPlatJmsProductor`、`xlyPlatJmsConsumer`、`xlyPlatReportForm`、`xlyPlatFileUpload`、`xlyPlatMarketingService`、`xlyPlatUserService`、`xlyPlatSmsService`、`xlyPlatMerchantController`、`xlyPlatWebsocket`、`xlyPlatPayService`、`xlyPlatCainiaoWaybillSevice`。(`xlyTestService` / `xlyTestController` 目录不在磁盘上;只有 `xlyEntry/.../businessweb/` 里存在一个空壳 `TestController.java`。)
维护人员清理代码库时应判断是否删除磁盘上但已排除的 `xlyErpTask` / `xlyRxtx` / `xlyFile` 目录,或保留为历史参考。它们占用磁盘空间,但不影响 build。
## Plat* 家族
`xlyPlat*` 模块(`xlyPlatMerchantController`、`xlyPlatUserService`、`xlyPlatPayService`、`xlyPlatMarketingService`、`xlyPlatCainiaoWaybillSevice`、`xlyPlatSmsService`、`xlyPlatReportForm`、`xlyPlatFileUpload`、`xlyPlatJmsConsumer` / `Productor`、`xlyPlatTask`、`xlyPlatWebsocket`)属于 **B2B 印刷平台层**,不在本 Wiki 范围内。唯一例外是 `xlyPlatConstant`,它仍在 `settings.gradle` 中启用,并被 `xlyPersist` 当作共享常量工具使用(`MultiThreadServer`、`TimeContant`)。
## 服务如何互相发现
三种通信通道:
1. **共享数据库**:每个服务读写同一个 MySQL schema。大多数跨服务“通信”是通过共享表隐式发生。
2. **消息**:代码库中同时存在 ActiveMQ / JMS 和 RocketMQ。ActiveMQ / JMS 路径用于基础数据合并和异步扇出;缓存失效不走 JMS,见[元数据变更后的缓存失效](cache-invalidation.md)。
3. **HTTP REST**:同步调用,例如 xlyApi 调用 xlyEntry 的 `/business/*` 端点。
除 `application-.yml` 中按环境硬编码的 peer URL 外,没有服务注册 / 发现机制。
## 部署环境中的 URL 路由
工作区 `.env.local` 在实时环境中把 **后台** 指向端口 `8597`,**前台** 指向端口 `8598`。这足以识别两个面向操作人员的接口面;反向代理和 context-path 映射属于部署细节,不是本仓库中有代码依据的事实。
## Profile 组合
Profile 按服务拆分:
- **xlyEntry**:`dev`、`local`、`win`、`linux`、`15s`、`s10`、`saas`、`bgj`(小写)。`dev` 是 repo 内默认。
- **xlyApi**:`local`(repo 默认)、`dev`、`linux`、`win`。
- **xlyInterface**:仅 `dev`。
- **xlyFlow**:`dev`(空文件)。
- **xlyFace**:`win`(默认)、`dev`、`linux`、`local`。
- **xlyPlc**:`dev`(默认)加 7 个机型 profile(`15S`、`S10`、`T0`、`T1`、`CT`、`yt`、`pro`,大小写混合;不同于 xlyEntry 的小写 `15s` / `s10`)。
机型 profile(`T0`、`T1`、`CT`、`yt`、`pro`、`15S`、`S10`)是 **xlyPlc 专用**,其他服务没有这些 profile。跨服务 profile 覆盖以下组合:
- 操作系统(`linux` / `win`)。
- 环境(`dev`、`local`、`saas`、`bgj`)。
- 客户 / 版本(xlyEntry 的 `15s`、`s10`)。
每个部署为每个服务选择一个 profile。“某客户 → 哪些 profile”的映射位于运维部署文档,不在代码库中。
## 未决:生产 URL 路由
> **暂缓(超出仓库可验证范围)。** 将公网 `:8597` / `:8598` 映射到内部 Spring Boot context-path 的 nginx / 反向代理配置位于部署运维基础设施中,不在本代码库里。Wiki 无法仅靠 src / DB / web 验证它;本节只是占位,等待部署侧配置被链接或纳入仓库。
`8597` / `8598` 的精确 nginx / 反向代理配置不在仓库中。只有拿到部署侧配置后再补入本页。