# 部署与运维
**本文引用的文件**
- [deploy/env.sh](file://deploy/env.sh)
- [cmd/uninstall.bat](file://cmd/uninstall.bat)
- [cmd/uninstall.sh](file://cmd/uninstall.sh)
- [ai-electron/package.json](file://ai-electron/package.json)
- [ai-electron/electron/config/config.default.ts](file://ai-electron/electron/config/config.default.ts)
- [ai-electron/electron/config/config.prod.ts](file://ai-electron/electron/config/config.prod.ts)
- [ai-electron/electron/config/windowOptions.ts](file://ai-electron/electron/config/windowOptions.ts)
- [ai-electron/electron/main.ts](file://ai-electron/electron/main.ts)
- [ai-electron/electron/preload/lifecycle.ts](file://ai-electron/electron/preload/lifecycle.ts)
- [ai-gateway/src/main/java/com/zsjz/gateway/GatewayApplication.java](file://ai-gateway/src/main/java/com/zsjz/gateway/GatewayApplication.java)
- [ai-gateway/src/main/resources/application.yaml](file://ai-gateway/src/main/resources/application.yaml)
- [ai-gateway/src/main/resources/application-pro.yaml](file://ai-gateway/src/main/resources/application-pro.yaml)
- [ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java](file://ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java)
- [ai-gateway/src/main/java/com/zsjz/gateway/registry/HealthChecker.java](file://ai-gateway/src/main/java/com/zsjz/gateway/registry/HealthChecker.java)
- [ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java](file://ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java)
- [ai-server/src/main/resources/application.yaml](file://ai-server/src/main/resources/application.yaml)
- [ai-server/src/main/resources/application-pro.yaml](file://ai-server/src/main/resources/application-pro.yaml)
- [ai-server/src/main/java/com/zsjz/ai/common/config/SaTokenWebConfig.java](file://ai-server/src/main/java/com/zsjz/ai/common/config/SaTokenWebConfig.java)
- [ai-server/src/main/java/com/zsjz/ai/module/plat/controller/SystemController.java](file://ai-server/src/main/java/com/zsjz/ai/module/plat/controller/SystemController.java)
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [生产环境前置依赖](#生产环境前置依赖)
4. [环境变量与服务配置](#环境变量与服务配置)
5. [服务启动顺序与差异](#服务启动顺序与差异)
6. [Electron 客户端构建、打包与自动更新](#electron-客户端构建打包与自动更新)
7. [多节点扩展方案](#多节点扩展方案)
8. [日志位置与监控指标](#日志位置与监控指标)
9. [备份恢复与数据生命周期](#备份恢复与数据生命周期)
10. [性能调优建议](#性能调优建议)
11. [常见故障排查清单](#常见故障排查清单)
12. [结论](#结论)
## 引言
本指南面向生产环境的部署与运维人员,覆盖 PostgreSQL/pgvector、Redis、DuckDB 初始化思路,后端环境变量配置,ai-gateway 与 ai-server 的启动顺序和配置差异,Electron 客户端构建打包及自动更新流程,Windows/Linux 安装包卸载脚本用法,以及多节点粘性路由、负载均衡、健康检查、故障转移、日志、监控、备份恢复、性能调优和排障清单。
## 项目结构
从部署视角,系统由以下主要组件构成:
- 桌面客户端:ai-electron(Electron + ee-core)
- 网关:ai-gateway(Spring Boot,按用户粘性转发到 ai-server)
- 业务后端:ai-server(Spring Boot,连接 PostgreSQL/pgvector、Redis、Elasticsearch、可选 Neo4j 和本地 DuckDB 实例)
- 外部依赖:PostgreSQL(含 pgvector)、Redis、Elasticsearch、文件系统存储目录
- 部署配置:deploy/env.sh
- 安装包卸载脚本:cmd/uninstall.bat、cmd/uninstall.sh
```mermaid
graph TB
Client["桌面客户端
ai-electron"] --> Gateway["网关
ai-gateway:8080"]
Gateway --> Server1["后端节点 A
ai-server:8980"]
Gateway --> Server2["后端节点 B
ai-server:8980"]
Gateway --> DB["PostgreSQL
pgvector"]
Gateway -.-> Redis["Redis
会话与粘性路由缓存"]
Server1 --> DB
Server1 --> ES["Elasticsearch"]
Server1 --> Files["本地文件存储
data/files"]
Server2 --> DB
Server2 --> ES
Server2 --> Files
```
**图示来源**
- [ai-gateway/src/main/resources/application.yaml:1-81](file://ai-gateway/src/main/resources/application.yaml#L1-L81)
- [ai-server/src/main/resources/application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
**章节来源**
- [ai-gateway/src/main/java/com/zsjz/gateway/GatewayApplication.java:1-23](file://ai-gateway/src/main/java/com/zsjz/gateway/GatewayApplication.java#L1-L23)
- [ai-gateway/src/main/resources/application.yaml:1-81](file://ai-gateway/src/main/resources/application.yaml#L1-L81)
- [ai-server/src/main/resources/application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
## 生产环境前置依赖
### PostgreSQL 与 pgvector
- 数据库名默认使用 `zsjz-ai`,驱动为 `org.postgresql.Driver`。
- 必须启用 pgvector 扩展,因为向量索引、模板语义检索、附件 RAG 等能力依赖该扩展。
- 主库地址、用户名、密码通过环境变量或 application-pro.yaml 注入;网关也共享同一套 PostgreSQL。
- 网关会在首次启动时执行幂等的建表 SQL,服务与节点元数据保存在网关自己的数据库中。
建议步骤:
1. 安装 PostgreSQL。
2. 创建数据库 `zsjz-ai`。
3. 启用 pgvector 扩展。
4. 初始化网关表结构(可复用仓库中的 gateway 相关 SQL)。
5. 校验端口、账号权限、网络连通性。
### Redis
- Redis 是登录态硬依赖:sa-token 将 token 映射到登录用户信息并写入 Redis。
- Redis 不可用会导致登录相关接口异常。
- 网关还使用 Redis 缓存“用户 -> ai-server 节点”的粘性路由键。
- 生产环境需设置独立密码,并通过环境变量或配置文件注入 host、port、database。
建议步骤:
1. 安装并启动 Redis。
2. 设置强密码。
3. 开放给 ai-gateway 和 ai-server 所在主机访问。
4. 校验连接后确认 sa-token 能读写 token。
### DuckDB
- DuckDB 不是常驻外部服务,而是以进程内或轻量实例形式管理案件库资源。
- 应用层通过 `ZSJZ_DUCKDB_MAX_OPEN_CASES` 控制同时打开的案件库数量上限,超出直接拒绝开案。
- DuckDB 内存预算、线程数、回收器延迟与间隔都可通过环境变量调整。
- 部署时需确保机器有足够内存,避免多个大案例并发导致堆外内存或系统内存压力。
建议步骤:
1. 评估单机 CPU 核数和内存。
2. 根据并发案例数调整 `ZSJZ_DUCKDB_MAX_OPEN_CASES`、`ZSJZ_DUCKDB_MEMORY_RATIO`、`ZSJZ_DUCKDB_THREADS_PER_INSTANCE`。
3. 观察启动后的兜底回收器日志,确认未出现大量资源泄漏。
**章节来源**
- [deploy/env.sh:1-172](file://deploy/env.sh#L1-L172)
- [ai-server/src/main/resources/application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
- [ai-gateway/src/main/resources/application.yaml:1-81](file://ai-gateway/src/main/resources/application.yaml#L1-L81)
- [ai-gateway/src/main/resources/application-pro.yaml:1-14](file://ai-gateway/src/main/resources/application-pro.yaml#L1-L14)
## 环境变量与服务配置
### deploy/env.sh 的作用
deploy/env.sh 集中声明了 ai-server 的环境变量,包括跨域、Spring 基础参数、PostgreSQL、Redis、Elasticsearch、本地存储、Neo4j、RAG、Insight、DuckDB、文件 AI 识别、Embedding、AI Clean、聊天附件解析、登录安全窗口等。其设计约定是:application.yaml 中的配置项写成 `${ENV_NAME:默认值}`,当未设置环境变量时使用 yaml 默认值;设置了环境变量则以环境变量为准。
典型用途:
- 在 Linux 上通过 `set -a; source deploy/env.sh; set +a` 再启动 ai-server。
- 在 systemd 单元中通过 `EnvironmentFile=/opt/zsjz-ai/deploy/env.sh` 注入。
注意事项:
- 文件中包含数据库口令,部署时应限制文件权限。
- 跨域开关默认开启,因为 Electron 前端可能通过 file:// 加载。
- Spring profile 由 `SPRING_PROFILES_ACTIVE` 控制,默认 dev;生产应改为 pro。
- Sa-Token、MyBatis-Plus 不参与此文件的参数化。
### 关键环境变量对照
| 类别 | 示例变量 | 说明 |
| --- | --- | --- |
| 跨域 | `APP_CORS_ENABLED`、`APP_CORS_ALLOWED_ORIGIN_PATTERNS` | Electron file:// 前端需要允许跨域 |
| Spring | `SPRING_TASK_SCHEDULING_POOL_SIZE`、`SPRING_HTTP_CODECS_MAX_IN_MEMORY_SIZE`、multipart 大小 | 调度线程池、HTTP 编码器和上传大小 |
| PostgreSQL | `SPRING_DATASOURCE_DYNAMIC_*_MASTER_*` | 主库 URL、用户名、密码、驱动 |
| Redis | `SPRING_DATA_REDIS_HOST`、`SPRING_DATA_REDIS_PORT` | sa-token 登录态依赖 |
| Elasticsearch | `SPRING_ELASTICSEARCH_URIS`、超时参数 | 全文检索集群地址 |
| 文件存储 | `STORAGE_LOCAL_ROOT_PATH`、`STORAGE_LOCAL_BASE_URL` | 根目录与对外基础 URL |
| DuckDB | `ZSJZ_DUCKDB_MAX_OPEN_CASES`、`ZSJZ_DUCKDB_MEMORY_RATIO`、`ZSJZ_DUCKDB_THREADS_PER_INSTANCE` | 案件库并发与资源预算 |
| Embedding | `ZSJZ_EMBEDDING_ENABLED`、`ZSJZ_EMBEDDING_MODEL_PATH`、`ZSJZ_EMBEDDING_DIMENSIONS` | 本地 ONNX 向量模型开关与路径 |
| AI Clean | `ZSJZ_AI_CLEAN_VECTOR_*` | 模板向量索引开关、阈值、重建策略 |
| Chat Attachment | `ZSJZ_CHAT_ATTACHMENT_*` | 对话附件大小、分块、RAG 召回条数 |
| Auth | `ZSJZ_AUTH_IN_USE_WINDOW_MINUTES` | 账号正在使用的判定窗口分钟数 |
**章节来源**
- [deploy/env.sh:1-172](file://deploy/env.sh#L1-L172)
- [ai-server/src/main/resources/application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
- [ai-server/src/main/resources/application-pro.yaml:1-87](file://ai-server/src/main/resources/application-pro.yaml#L1-L87)
## 服务启动顺序与差异
### 推荐启动顺序
1. 启动 PostgreSQL、Redis、Elasticsearch。
2. 启动 ai-server(至少一个节点)。
3. 启动 ai-gateway。
4. 验证 `/js/a/sys/health` 和网关管理端可用性。
5. 启动 Electron 客户端。
原因:
- ai-server 提供业务接口和健康端点。
- ai-gateway 依赖 ai-server 的健康端点进行节点探活,并依赖 Redis 做粘性路由缓存。
- Electron 客户端通过网关访问后端,若后端未就绪会失败。
### ai-server 配置要点
- 默认监听 `8980`,上下文路径 `/js/a`。
- 跨域开关受 `app.cors.*` 控制,生产应根据固定域名收敛允许来源。
- Sa-Token 通过请求头 `x-token` 传递,token 有效期 30 天,默认单端登录,支持通过 JVM 参数或环境变量开启多端。
- 向量能力依赖 pgvector 和可用 embedding 模型;缺失时链路 fail-open。
- 文件存储根目录默认为 `./data/files`,对外基础 URL 应与端口和上下文路径一致。
### ai-gateway 配置要点
- 默认监听 `8080`。
- Sa-Token 配置必须与 ai-server 保持一致,否则无法正确解析 token。
- 服务定义包含 path-prefix、login-path、health-path、default-node-id 和 nodes 列表。
- 健康检查周期、超时、失败阈值可配置。
- 生产环境可通过 application-pro.yaml 通过 PG_URL、PG_USER、PG_PASSWORD、REDIS_HOST 等环境变量覆盖数据库和 Redis 配置。
### 启动命令参考
- ai-server:从部署根目录执行 `java -jar ai-server.jar`,并确保已 source env.sh 或通过 systemd EnvironmentFile 注入。
- ai-gateway:执行 `java -jar ai-gateway.jar`,并使用 Spring profile pro。
```mermaid
sequenceDiagram
participant Admin as "运维"
participant Postgres as "PostgreSQL"
participant Redis as "Redis"
participant Server as "ai-server"
participant Gateway as "ai-gateway"
participant Client as "Electron 客户端"
Admin->>Postgres: 启动并初始化数据库
Admin->>Redis: 启动并设置密码
Admin->>Server: 启动后端节点
Server->>Postgres: 连接主库
Server->>Redis: 连接会话缓存
Admin->>Gateway: 启动网关
Gateway->>Server: 周期性探测 /js/a/sys/health
Client->>Gateway: 发起业务请求
Gateway->>Server: 转发到粘性节点
```
**图示来源**
- [ai-gateway/src/main/resources/application.yaml:1-81](file://ai-gateway/src/main/resources/application.yaml#L1-L81)
- [ai-server/src/main/resources/application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
**章节来源**
- [ai-gateway/src/main/resources/application.yaml:1-81](file://ai-gateway/src/main/resources/application.yaml#L1-L81)
- [ai-gateway/src/main/resources/application-pro.yaml:1-14](file://ai-gateway/src/main/resources/application-pro.yaml#L1-L14)
- [ai-server/src/main/resources/application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
- [ai-server/src/main/resources/application-pro.yaml:1-87](file://ai-server/src/main/resources/application-pro.yaml#L1-L87)
## Electron 客户端构建、打包与自动更新
### 构建与打包命令
package.json 定义了常用脚本:
- `npm run build`:构建前端、构建 Electron、加密。
- `npm run build-w`:构建 Windows 64 位。
- `npm run build-we`:构建 Windows 企业版。
- `npm run build-m`:构建 macOS。
- `npm run build-m-arm64`:构建 macOS ARM64。
- `npm run build-l`:构建 Linux。
这些命令通过 ee-bin 调用 electron-builder,并按平台读取对应的 builder 配置。
### 运行时配置
- 默认入口是 `public/electron/main.js`。
- 默认关闭开发者工具,生产配置进一步确保不打开调试窗口。
- 窗口选项使用 ee-core 提供的 webPreferences,默认启用 nodeIntegration 并禁用 contextIsolation,主窗口与智能工作台窗口共用相同偏好以避免行为不一致。
- 日志级别默认 info,按日滚动,单个日志文件最大 100MB,日志名称包括应用日志、核心日志和错误日志。
- mainServer 协议为 file://,索引路径指向打包后的前端静态资源。
### 自动更新
项目依赖 `electron-updater`,并在各平台 builder 配置中包含 publish 字段,用于指定更新源。通常自动更新流程如下:
1. 发布新版安装包到配置的更新服务器。
2. 生成 latest.yml 等版本描述文件。
3. 客户端启动时检查最新版本。
4. 发现新版本后下载并提示或静默安装。
生产部署时需注意:
- 更新服务器必须可被客户端访问。
- latest.yml 的版本号必须与 package.json 版本号一致。
- 如果后端升级了 API,应先完成服务端灰度再推送客户端版本。
### 客户端生命周期
main.ts 注册 ee-core 生命周期钩子,preload/lifecycle.ts 处理 ready、electron-app-ready、window-ready、before-close 等阶段,负责显示窗口、居中缩放、二次启动聚焦、智能工作台窗口优先聚焦等行为。
```mermaid
flowchart TD
Start["运行 npm run build-*"] --> Frontend["构建前端资源"]
Frontend --> ElectronBuild["构建 Electron 应用"]
ElectronBuild --> Package["打包为 Windows/macOS/Linux 安装包"]
Package --> Publish["发布到更新服务器"]
Publish --> ClientCheck["客户端启动检查更新"]
ClientCheck --> Update["下载并安装新版本"]
Update --> Run["运行新版本客户端"]
```
**图示来源**
- [ai-electron/package.json:1-42](file://ai-electron/package.json#L1-L42)
- [ai-electron/electron/main.ts:1-19](file://ai-electron/electron/main.ts#L1-L19)
- [ai-electron/electron/preload/lifecycle.ts:1-73](file://ai-electron/electron/preload/lifecycle.ts#L1-L73)
**章节来源**
- [ai-electron/package.json:1-42](file://ai-electron/package.json#L1-L42)
- [ai-electron/electron/config/config.default.ts:1-50](file://ai-electron/electron/config/config.default.ts#L1-L50)
- [ai-electron/electron/config/config.prod.ts:1-10](file://ai-electron/electron/config/config.prod.ts#L1-L10)
- [ai-electron/electron/config/windowOptions.ts:1-41](file://ai-electron/electron/config/windowOptions.ts#L1-L41)
- [ai-electron/electron/main.ts:1-19](file://ai-electron/electron/main.ts#L1-L19)
- [ai-electron/electron/preload/lifecycle.ts:1-73](file://ai-electron/electron/preload/lifecycle.ts#L1-L73)
## 多节点扩展方案
### 架构目标
- 多个 ai-server 节点共同承载业务。
- 网关按用户粘性路由,保证同一用户的请求尽量落到同一节点,避免状态不一致。
- 健康检查持续探测每个节点,连续失败标记 DOWN,一次成功恢复 UP。
- 管理端支持绑定用户到指定节点、导入已有绑定关系。
### 粘性路由与健康检查
- 用户路由缓存键包含 serviceId、userId、username,存储在 Redis 中。
- 健康检查每 `gateway.health-check.interval` 秒对启用的节点调用 `{base-url}{health-path}`。
- 连续失败达到 `gateway.health-check.failure-threshold` 次后节点标记 DOWN;一次成功即恢复 UP。
- 网关默认 health-path 为 `/js/a/sys/health`,对应 ai-server 的系统健康接口。
```mermaid
classDiagram
class HealthChecker {
+周期性探测()
+记录成功(nodeId)
+记录失败(nodeId, error, threshold)
}
class NodeHealthRegistry {
+快照()
+是否存活(nodeId) bool
+记录成功(nodeId)
+记录失败(nodeId, error, threshold)
}
class UserRouteService {
+查找路由(serviceId, userId) Mono
+绑定不存在(serviceId, userId, username, nodeId) Mono
+缓存用户(serviceId, userId, username, nodeId) Mono
}
class AdminService {
+绑定用户(serviceId, userId, username, nodeId)
+导入已有绑定(serviceId, nodeId) int
+检查节点(nodeId) Mono
}
HealthChecker --> NodeHealthRegistry : "更新状态"
UserRouteService --> NodeHealthRegistry : "判断节点存活"
AdminService --> UserRouteService : "写入粘性路由"
```
**图示来源**
- [ai-gateway/src/main/java/com/zsjz/gateway/registry/HealthChecker.java:1-60](file://ai-gateway/src/main/java/com/zsjz/gateway/registry/HealthChecker.java#L1-L60)
- [ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java:1-90](file://ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java#L1-L90)
- [ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java:1-290](file://ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java#L1-L290)
### 负载均衡策略
当前实现以“用户粘性”为主,不是无状态轮询负载均衡。这意味着:
- 同一用户登录后,网关会将其绑定到某个 ai-server 节点。
- 适合需要会话或局部状态的推理、研判场景。
- 如果需要全局均匀负载,应在网关之上再加一层反向代理做请求级负载均衡,但要注意长连接和 SSE 场景。
### 健康检查与故障转移
- 健康检查只证明进程存活,不深入检查 PostgreSQL、Redis、Elasticsearch 是否全部正常。
- 若节点 DOWN,粘性路由不会主动把在线用户迁移到其它节点;新绑定或重新绑定时才会选择可用节点。
- 运维可在管理端手动触发节点检查、解绑、删除节点或重新导入绑定关系。
### 配置差异总结
| 项目 | ai-server | ai-gateway |
| --- | --- | --- |
| 默认端口 | 8980 | 8080 |
| 上下文路径 | /js/a | 不统一业务路径,仅转发 |
| 主库 | PostgreSQL/pgvector | 自身服务元数据 |
| Redis | sa-token 登录态 | 粘性路由缓存 |
| Elasticsearch | 全文检索 | 不使用 |
| 健康端点 | /js/a/sys/health | 使用业务健康端点 |
| Sa-Token | 认证主体 | 只读 token->loginId |
**章节来源**
- [ai-gateway/src/main/resources/application.yaml:1-81](file://ai-gateway/src/main/resources/application.yaml#L1-L81)
- [ai-gateway/src/main/java/com/zsjz/gateway/registry/HealthChecker.java:1-60](file://ai-gateway/src/main/java/com/zsjz/gateway/registry/HealthChecker.java#L1-L60)
- [ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java:1-90](file://ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java#L1-L90)
- [ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java:1-290](file://ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java#L1-L290)
## 日志位置与监控指标
### 日志位置
- Electron 客户端日志由 ee-core 管理,默认输出到应用日志、核心日志和错误日志文件,日志级别为 info,按日滚动,单文件最大 100MB。
- 后端日志取决于 Spring Boot 默认配置和具体日志框架实现;健康检查状态也会记录节点 UP/DOWN 信息。
排查建议:
- 先查看 Electron 应用的错误日志。
- 再查看 ai-server 的业务日志和调度日志。
- 最后查看 ai-gateway 的健康检查日志和管理端操作日志。
### 监控指标
- 进程存活:操作系统级进程状态、CPU、内存、磁盘、网络。
- 服务健康:`GET http://host:8980/js/a/sys/health`。
- 网关健康:网关自身的 Spring Boot 健康端点和管理端接口。
- 数据库连接:PostgreSQL 活跃连接数、慢查询。
- Redis:连接数、内存、持久化状态。
- Elasticsearch:集群健康、索引大小、查询延迟。
- DuckDB:同时打开案例数、内存使用、回收器扫描日志。
- 向量模型:ONNX Runtime 加载耗时、批推理吞吐、失败重试次数。
**章节来源**
- [ai-electron/electron/config/config.default.ts:1-50](file://ai-electron/electron/config/config.default.ts#L1-L50)
- [ai-gateway/src/main/java/com/zsjz/gateway/registry/NodeHealthRegistry.java:1-70](file://ai-gateway/src/main/java/com/zsjz/gateway/registry/NodeHealthRegistry.java#L1-L70)
- [ai-server/src/main/java/com/zsjz/ai/module/plat/controller/SystemController.java:1-60](file://ai-server/src/main/java/com/zsjz/ai/module/plat/controller/SystemController.java#L1-L60)
## 备份恢复与数据生命周期
### 备份范围
| 数据 | 备份方式 | 恢复要点 |
| --- | --- | --- |
| PostgreSQL | 逻辑备份或物理备份 | 保留 schema、pgvector 扩展、业务表、网关表 |
| Redis | 持久化文件或云托管备份 | 注意 token 过期策略和粘性路由键 |
| 本地文件存储 | 同步 data/files 目录 | base-url 需与部署地址一致 |
| Electron 用户数据 | 用户目录下的 qingjian-client 相关目录 | 卸载脚本会清理 |
### 恢复顺序
1. 恢复 PostgreSQL。
2. 恢复 Redis。
3. 恢复本地文件存储目录。
4. 启动 ai-server。
5. 启动 ai-gateway。
6. 验证登录、粘性路由、向量索引、文件访问。
### 数据生命周期
- Insight 会话可配置留存天数,0 表示不清理。
- 聊天附件存在孤儿清理机制,长时间未发消息的附件会被清理。
- AI Clean 批次心跳超时会标失败,可由看门狗处理。
- DuckDB 案件库有兜底回收器,定期扫描释放资源。
**章节来源**
- [ai-server/src/main/resources/application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
- [cmd/uninstall.sh:1-53](file://cmd/uninstall.sh#L1-L53)
## 性能调优建议
### ai-server
- 合理设置 `SPRING_TASK_SCHEDULING_POOL_SIZE`,避免批量任务拖住 SSE 心跳。
- 根据上传文件大小调整 multipart 大小限制。
- 根据机器内存和并发案例数调整 DuckDB 的最大案例数、内存比例和线程数。
- 向量模型首次加载可能占用较大堆外内存,生产建议预热或预留足够内存。
- 若使用本地 embedding 模型,确认模型路径、维度、优化级别与机器性能匹配。
### ai-gateway
- 调整健康检查间隔、超时和失败阈值,平衡检测灵敏度与后端压力。
- 网关默认不对跨域做额外收口,避免重复 Access-Control-Allow-Origin 头。
- 管理端 IP 白名单可用于限制敏感管理接口。
### Electron 客户端
- 生产构建关闭开发工具。
- 窗口大小和最小尺寸应避免过小影响图表和表格展示。
- 日志滚动大小可根据磁盘空间调整。
**章节来源**
- [ai-server/src/main/resources/application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
- [ai-gateway/src/main/resources/application.yaml:1-81](file://ai-gateway/src/main/resources/application.yaml#L1-L81)
- [ai-electron/electron/config/config.prod.ts:1-10](file://ai-electron/electron/config/config.prod.ts#L1-L10)
## 常见故障排查清单
| 现象 | 可能原因 | 排查步骤 |
| --- | --- | --- |
| 登录失败 | Redis 不可用或 sa-token 配置不一致 | 检查 Redis 连通性、host/port/password;核对 ai-server 与 ai-gateway 的 Sa-Token 配置 |
| 跨域报错 | 前端 file:// 或浏览器跨域被拒绝 | 检查 `APP_CORS_ENABLED`、`APP_CORS_ALLOWED_ORIGIN_PATTERNS`;必要时收敛允许来源 |
| 向量功能不可用 | pgvector 未启用或 embedding 模型缺失 | 检查 pgvector 扩展、模型路径、维度、模型目录是否存在 |
| 开案失败 | DuckDB 并发超限或内存不足 | 查看 `ZSJZ_DUCKDB_MAX_OPEN_CASES`、机器内存、DuckDB 回收日志 |
| 健康检查一直 DOWN | 后端健康端点不可达或路径错误 | 检查 `{base-url}/js/a/sys/health`、网关 health-path、节点 base-url |
| 用户请求总是落到不同节点 | 粘性路由未命中或 Redis 丢失 | 检查 Redis 中路由缓存键、是否重启后丢失、是否手动解绑 |
| 文件访问链接无效 | storage.local.base-url 与实际部署地址不一致 | 核对 server.port、context-path、base-url |
| 客户端启动白屏或打不开 | 前端资源路径错误或 mainServer 配置异常 | 检查构建产物、index.html 路径、日志中的 mainServer 配置 |
| 安装包卸载后仍残留数据 | 卸载脚本未执行或未以正确用户运行 | 以目标用户运行 cmd/uninstall.sh 或 cmd/uninstall.bat |
### 卸载脚本用法
- Linux:`cmd/uninstall.sh` 会强制终止 qingjian-client 进程,然后递归删除用户目录下三个可能目录:`$HOME/.config/qingjian-client`、`$HOME/.local/share/QingJian`、`$HOME/.qingjian-client`。
- Windows:`cmd/uninstall.bat` 提供对应卸载清理流程,应与 Linux 脚本配合使用,确保跨平台一致性。
**章节来源**
- [ai-server/src/main/java/com/zsjz/ai/common/config/SaTokenWebConfig.java:1-40](file://ai-server/src/main/java/com/zsjz/ai/common/config/SaTokenWebConfig.java#L1-L40)
- [ai-server/src/main/java/com/zsjz/ai/module/plat/controller/SystemController.java:1-60](file://ai-server/src/main/java/com/zsjz/ai/module/plat/controller/SystemController.java#L1-L60)
- [cmd/uninstall.sh:1-53](file://cmd/uninstall.sh#L1-L53)
- [cmd/uninstall.bat:1-53](file://cmd/uninstall.bat#L1-L53)
## 结论
生产部署应以 PostgreSQL/pgvector、Redis、Elasticsearch 为底座,按顺序启动 ai-server 和 ai-gateway,并通过 deploy/env.sh 统一管理环境变量。多节点扩展以用户粘性路由为主,配合健康检查和治理接口实现高可用。Electron 客户端通过 electron-builder 和 electron-updater 完成构建、打包与自动更新。运维重点在于 Redis 与 PgVector 可用性、DuckDB 资源预算、向量模型路径、跨域配置、健康检查路径、日志位置和卸载脚本的正确使用。