部署与运维.md 27 KB

部署与运维

本文引用的文件

  • deploy/env.sh
  • cmd/uninstall.bat
  • cmd/uninstall.sh
  • ai-electron/package.json
  • ai-electron/electron/config/config.default.ts
  • ai-electron/electron/config/config.prod.ts
  • ai-electron/electron/config/windowOptions.ts
  • ai-electron/electron/main.ts
  • ai-electron/electron/preload/lifecycle.ts
  • ai-gateway/src/main/java/com/zsjz/gateway/GatewayApplication.java
  • ai-gateway/src/main/resources/application.yaml
  • ai-gateway/src/main/resources/application-pro.yaml
  • ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java
  • ai-gateway/src/main/java/com/zsjz/gateway/registry/HealthChecker.java
  • ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java
  • ai-server/src/main/resources/application.yaml
  • ai-server/src/main/resources/application-pro.yaml
  • 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

目录

  1. 引言
  2. 项目结构
  3. 生产环境前置依赖
  4. 环境变量与服务配置
  5. 服务启动顺序与差异
  6. 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

    graph TB
    Client["桌面客户端<br/>ai-electron"] --> Gateway["网关<br/>ai-gateway:8080"]
    Gateway --> Server1["后端节点 A<br/>ai-server:8980"]
    Gateway --> Server2["后端节点 B<br/>ai-server:8980"]
    Gateway --> DB["PostgreSQL<br/>pgvector"]
    Gateway -.-> Redis["Redis<br/>会话与粘性路由缓存"]
    Server1 --> DB
    Server1 --> ES["Elasticsearch"]
    Server1 --> Files["本地文件存储<br/>data/files"]
    Server2 --> DB
    Server2 --> ES
    Server2 --> Files
    

图示来源

  • ai-gateway/src/main/resources/application.yaml:1-81
  • ai-server/src/main/resources/application.yaml:1-193

章节来源

  • ai-gateway/src/main/java/com/zsjz/gateway/GatewayApplication.java:1-23
  • ai-gateway/src/main/resources/application.yaml:1-81
  • ai-server/src/main/resources/application.yaml:1-193

生产环境前置依赖

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
  • ai-server/src/main/resources/application.yaml:1-193
  • ai-gateway/src/main/resources/application.yaml:1-81
  • ai-gateway/src/main/resources/application-pro.yaml:1-14

环境变量与服务配置

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
  • ai-server/src/main/resources/application.yaml:1-193
  • ai-server/src/main/resources/application-pro.yaml:1-87

服务启动顺序与差异

推荐启动顺序

  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。

    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
  • ai-server/src/main/resources/application.yaml:1-193

章节来源

  • ai-gateway/src/main/resources/application.yaml:1-81
  • ai-gateway/src/main/resources/application-pro.yaml:1-14
  • ai-server/src/main/resources/application.yaml:1-193
  • ai-server/src/main/resources/application-pro.yaml:1-87

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 等阶段,负责显示窗口、居中缩放、二次启动聚焦、智能工作台窗口优先聚焦等行为。

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
  • ai-electron/electron/main.ts:1-19
  • ai-electron/electron/preload/lifecycle.ts:1-73

章节来源

  • ai-electron/package.json:1-42
  • ai-electron/electron/config/config.default.ts:1-50
  • ai-electron/electron/config/config.prod.ts:1-10
  • ai-electron/electron/config/windowOptions.ts:1-41
  • ai-electron/electron/main.ts:1-19
  • ai-electron/electron/preload/lifecycle.ts:1-73

多节点扩展方案

架构目标

  • 多个 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 的系统健康接口。

    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
  • ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java:1-90
  • ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java:1-290

负载均衡策略

当前实现以“用户粘性”为主,不是无状态轮询负载均衡。这意味着:

  • 同一用户登录后,网关会将其绑定到某个 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
  • ai-gateway/src/main/java/com/zsjz/gateway/registry/HealthChecker.java:1-60
  • ai-gateway/src/main/java/com/zsjz/gateway/route/UserRouteService.java:1-90
  • ai-gateway/src/main/java/com/zsjz/gateway/admin/AdminService.java:1-290

日志位置与监控指标

日志位置

  • 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
  • ai-gateway/src/main/java/com/zsjz/gateway/registry/NodeHealthRegistry.java:1-70
  • ai-server/src/main/java/com/zsjz/ai/module/plat/controller/SystemController.java:1-60

备份恢复与数据生命周期

备份范围

数据 备份方式 恢复要点
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
  • cmd/uninstall.sh:1-53

性能调优建议

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
  • ai-gateway/src/main/resources/application.yaml:1-81
  • ai-electron/electron/config/config.prod.ts:1-10

常见故障排查清单

现象 可能原因 排查步骤
登录失败 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
  • ai-server/src/main/java/com/zsjz/ai/module/plat/controller/SystemController.java:1-60
  • cmd/uninstall.sh:1-53
  • cmd/uninstall.bat:1-53

结论

生产部署应以 PostgreSQL/pgvector、Redis、Elasticsearch 为底座,按顺序启动 ai-server 和 ai-gateway,并通过 deploy/env.sh 统一管理环境变量。多节点扩展以用户粘性路由为主,配合健康检查和治理接口实现高可用。Electron 客户端通过 electron-builder 和 electron-updater 完成构建、打包与自动更新。运维重点在于 Redis 与 PgVector 可用性、DuckDB 资源预算、向量模型路径、跨域配置、健康检查路径、日志位置和卸载脚本的正确使用。