# 多服务部署

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<br/>http://&lt;host&gt;:8597"]
      FROUNT["FROUNT SPA<br/>http://&lt;host&gt;:8598"]
    end
    EXT([外部集成方])
    HOOKS([第三方 webhook])

    subgraph boots [可部署 Spring Boot 应用]
      direction TB
      XENTRY["xlyEntry<br/>:8080  /xlyEntry<br/>EntryApplicationBoot"]:::boot
      XAPI["xlyApi<br/>:8090 (local) / :8080<br/>/xlyApi · ApiApplicationBoot"]:::boot
      XIF["xlyInterface<br/>:8080  /xlyInterface<br/>InterfaceApplicationBoot"]:::boot
      XPLC["xlyPlc<br/>:8000 (dev) / :8080<br/>/xlyEntry · PlcApplicationBoot"]:::boot
      XFACE["xlyFace<br/>:8091 (local) / :8080<br/>/xlyFace（文档范围外）"]:::boot
      XEJMSC["xlyErpJmsConsumer<br/>（无端口；继承配置）<br/>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<br/>xlyweberp_*")]
      REDIS[(Redis :16379<br/>共享缓存 + session)]
      AMQ([ActiveMQ :61616])
      MONGO[("MongoDB<br/>已接线但未使用")]
    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-<profile>.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-<profile>.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 / 反向代理配置不在仓库中。只有拿到部署侧配置后再补入本页。
