# Spring Boot 应用入口与启动流程
**本文引用的文件**
- [pom.xml](file://pom.xml)
- [ai-server/pom.xml](file://ai-server/pom.xml)
- [App.java](file://ai-server/src/main/java/com/zsjz/ai/App.java)
- [application.yaml](file://ai-server/src/main/resources/application.yaml)
- [application-dev.yaml](file://ai-server/src/main/resources/application-dev.yaml)
- [application-pro.yaml](file://ai-server/src/main/resources/application-pro.yaml)
- [DataSourceConfig.java](file://ai-server/src/main/java/com/zsjz/ai/common/config/DataSourceConfig.java)
- [CaseDataSourceReaper.java](file://ai-server/src/main/java/com/zsjz/ai/common/datasource/CaseDataSourceReaper.java)
- [AppLoadEndEventListener.java](file://ai-server/src/main/java/com/zsjz/ai/common/event/AppLoadEndEventListener.java)
- [SearchIndexInitializer.java](file://ai-server/src/main/java/com/zsjz/ai/module/search/service/SearchIndexInitializer.java)
- [AiCleanWatchdog.java](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanWatchdog.java)
- [AiCleanTemplateVectorIndex.java](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/index/AiCleanTemplateVectorIndex.java)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能与启动特性](#性能与启动特性)
8. [常见问题排查](#常见问题排查)
9. [结论](#结论)
## 简介
本文面向 ai-server Spring Boot 应用,聚焦其应用入口、包扫描范围、模块依赖加载方式,以及基于 Spring Boot 3.5 + Java 25 的启动阶段横切能力。重点说明多数据源初始化、Redis 连接、Agent 工作区与系统目录初始化、全文检索索引创建、智能清洗批次恢复与看门狗、向量索引自举等 `ApplicationRunner` / `CommandLineRunner` / `ApplicationListener` 行为,并解释配置文件组织与环境变量覆盖机制。
## 项目结构
ai-server 是 Maven 子模块,位于仓库根 `pom.xml` 的 modules 中;父 POM 继承 Spring Boot 3.5.16 的 starter parent,因此 Spring Boot 版本由父 POM 统一约束。ai-server 自身声明 Java 25,并通过多个 Spring Boot Starter 引入 Web、Validation、Data Redis、AOP、Sa-Token、MyBatis-Plus、动态数据源、AgentScope、PostgreSQL、pgvector、DuckDB、Tika、DJL HuggingFace Tokenizers 和 ONNX Runtime 等能力。
```mermaid
graph TB
RootPOM["根 POM
Spring Boot 3.5.16"] --> ServerModule["ai-server 子模块
Java 25"]
ServerModule --> SpringBootStarterWeb["spring-boot-starter-web"]
ServerModule --> SpringBootStarterValidation["spring-boot-starter-validation"]
ServerModule --> SpringBootStarterDataRedis["spring-boot-starter-data-redis"]
ServerModule --> SpringBootStarterAop["spring-boot-starter-aop"]
ServerModule --> SaToken["sa-token-spring-boot3-starter"]
ServerModule --> MybatisPlus["mybatis-plus-spring-boot3-starter"]
ServerModule --> DynamicDatasource["dynamic-datasource-spring-boot3-starter"]
ServerModule --> AgentScope["agentscope-harness 及扩展"]
ServerModule --> PostgreSQL["postgresql 驱动"]
ServerModule --> PgVector["com.pgvector pgvector"]
ServerModule --> DuckDB["duckdb_jdbc"]
ServerModule --> Tika["spring-ai-tika-document-reader"]
ServerModule --> DJL["ai.djl.huggingface tokenizers"]
ServerModule --> OnnxRuntime["onnxruntime"]
```
**图示来源**
- [pom.xml:1-23](file://pom.xml#L1-L23)
- [ai-server/pom.xml:1-40](file://ai-server/pom.xml#L1-L40)
- [ai-server/pom.xml:40-200](file://ai-server/pom.xml#L40-L200)
**章节来源**
- [pom.xml:1-23](file://pom.xml#L1-L23)
- [ai-server/pom.xml:1-40](file://ai-server/pom.xml#L1-L40)
## 核心组件
- **应用主类**:`com.zsjz.ai.App` 是 Spring Boot 启动入口,启用调度任务注解,并使用 `SpringApplication.run` 启动容器。
- **配置中心**:`application.yaml` 定义通用配置与业务配置命名空间,`application-dev.yaml` 与 `application-pro.yaml` 按 profile 注入数据库、Redis、Elasticsearch、存储路径、Sa-Token 和 Neo4j 等环境差异配置。
- **数据源路由**:通过自定义 `DataSourceConfig` 替换动态数据源自动装配的默认路由,使 `@DS("slave")` 能结合案件上下文动态路由到 DuckDB 案件库。
- **启动期横切逻辑**:`AppLoadEndEventListener`(`CommandLineRunner`)、`SearchIndexInitializer`(`ApplicationRunner`)、`AiCleanWatchdog`(`ApplicationReadyEvent`)、`AiCleanTemplateVectorIndex`(`ApplicationReadyEvent`)在启动不同阶段执行清理、缓存预热、索引重建或恢复操作。
**章节来源**
- [App.java:1-49](file://ai-server/src/main/java/com/zsjz/ai/App.java#L1-L49)
- [application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
- [application-dev.yaml:1-87](file://ai-server/src/main/resources/application-dev.yaml#L1-L87)
- [application-pro.yaml:1-87](file://ai-server/src/main/resources/application-pro.yaml#L1-L87)
- [DataSourceConfig.java:1-38](file://ai-server/src/main/java/com/zsjz/ai/common/config/DataSourceConfig.java#L1-L38)
## 架构总览
应用以 Spring Boot 容器为中心,启动后完成以下关键横切能力:
1. 解析 `application.yaml` 与各 profile 配置,启用定时任务线程池、跨域、上传大小限制、AI 研判、DuckDB 预算、向量模型开关、智能清洗配置、Agent RAG、Sa-Token 等。
2. 初始化 PostgreSQL 主数据源与动态数据源;使用 `CaseRoutingDataSource` 将业务 SQL 中的 `@DS("slave")` 路由到当前用户打开的案件 DuckDB 数据源。
3. 初始化 Redis 连接,供 Sa-Token 会话、登录态、全局缓存、案件缓存、健康检查等使用。
4. 创建系统目录与 Agent 工作区目录,初始化全局缓存、RocksDB 数据目录。
5. 幂等创建 Elasticsearch 全文检索索引;若 ES 不可用则降级,不阻断启动。
6. 应用就绪后:
- 将上一轮未完成的智能清洗批次标记为失败,允许用户重新发起。
- 后台检测模板向量索引是否缺失或为空,必要时进行全量重建。
7. 运行期定时任务:SSE 心跳、数据源兜底回收、智能清洗看门狗、附件清理等。
```mermaid
sequenceDiagram
participant JVM as "JVM"
participant App as "App 主类"
participant Spring as "Spring 容器"
participant Config as "配置与数据源"
participant Redis as "Redis"
participant Runner as "CommandLineRunner / ApplicationRunner"
participant Ready as "ApplicationReadyEvent 监听器"
participant Scheduler as "定时任务"
JVM->>App: 调用 main()
App->>Spring: SpringApplication.run(App.class, args)
Spring->>Config: 加载 application.yaml 与 profile
Spring->>Config: 初始化 PostgreSQL 与动态数据源
Spring->>Redis: 初始化 Redis 连接
Spring-->>Runner: 触发 CommandLineRunner / ApplicationRunner
Runner->>Runner: 创建系统目录与 Agent 工作区
Runner->>Runner: 初始化全局缓存与 RocksDB
Spring-->>Ready: 触发 ApplicationReadyEvent
Ready->>Ready: 恢复上一轮智能清洗批次
Ready->>Ready: 检测并可能重建模板向量索引
Spring->>Scheduler: 启动 SSE 心跳、数据源回收、看门狗等定时任务
```
**图示来源**
- [App.java:23-33](file://ai-server/src/main/java/com/zsjz/ai/App.java#L23-L33)
- [application.yaml:1-193](file://ai-server/src/main/resources/application.yaml#L1-L193)
- [DataSourceConfig.java:20-38](file://ai-server/src/main/java/com/zsjz/ai/common/config/DataSourceConfig.java#L20-L38)
- [AppLoadEndEventListener.java:15-58](file://ai-server/src/main/java/com/zsjz/ai/common/event/AppLoadEndEventListener.java#L15-L58)
- [SearchIndexInitializer.java:18-30](file://ai-server/src/main/java/com/zsjz/ai/module/search/service/SearchIndexInitializer.java#L18-L30)
- [AiCleanWatchdog.java:64-95](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanWatchdog.java#L64-L95)
- [AiCleanTemplateVectorIndex.java:221-260](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/index/AiCleanTemplateVectorIndex.java#L221-L260)
## 详细组件分析
### 应用主类与包扫描范围
`App` 使用 `@SpringBootApplication`,因此 Spring Boot 默认从 `com.zsjz.ai` 开始扫描组件。代码中没有显式 `@ComponentScan`,也没有对 `@MapperScan` 做全局扫描;注释明确说明 Mapper 依靠类上的 `@Mapper` 注解注册。这意味着新增 Mapper 必须添加 `@Mapper`,否则会因找不到映射而启动失败或运行时异常。
```mermaid
classDiagram
class App {
+main(args)
+init()
}
class DataSourceConfig {
+caseRoutingDataSource(providers, properties)
}
class AppLoadEndEventListener {
+run(args)
}
class SearchIndexInitializer {
+run(args)
}
class AiCleanWatchdog {
+failOrphansOnStartup(event)
+failStale()
}
class AiCleanTemplateVectorIndex {
+onApplicationReady(event)
+rebuildAsync()
+isAvailable()
}
App --> DataSourceConfig : "容器装配"
App --> AppLoadEndEventListener : "启动后执行"
App --> SearchIndexInitializer : "启动后执行"
App --> AiCleanWatchdog : "应用就绪后执行"
App --> AiCleanTemplateVectorIndex : "应用就绪后执行"
```
**图示来源**
- [App.java:15-33](file://ai-server/src/main/java/com/zsjz/ai/App.java#L15-L33)
- [DataSourceConfig.java:20-38](file://ai-server/src/main/java/com/zsjz/ai/common/config/DataSourceConfig.java#L20-L38)
- [AppLoadEndEventListener.java:15-58](file://ai-server/src/main/java/com/zsjz/ai/common/event/AppLoadEndEventListener.java#L15-L58)
- [SearchIndexInitializer.java:18-30](file://ai-server/src/main/java/com/zsjz/ai/module/search/service/SearchIndexInitializer.java#L18-L30)
- [AiCleanWatchdog.java:64-95](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanWatchdog.java#L64-L95)
- [AiCleanTemplateVectorIndex.java:221-260](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/index/AiCleanTemplateVectorIndex.java#L221-L260)
**章节来源**
- [App.java:15-33](file://ai-server/src/main/java/com/zsjz/ai/App.java#L15-L33)
- [AiCleanTemplateVectorIndex.java:221-260](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/index/AiCleanTemplateVectorIndex.java#L221-L260)
### 多数据源初始化与案件数据源回收
项目使用 dynamic-datasource 管理 PostgreSQL 主库,同时通过 `CaseRoutingDataSource` 替换默认的 `DynamicRoutingDataSource`,使 `@DS("slave")` 能够根据当前会话中的 caseId 路由到 DuckDB 案件库。`DataSourceConfig` 把 dynamic-datasource 的 primary、strict、strategy、p6spy、seata、graceDestroy 等属性手动拷贝到自定义数据源上,否则这些配置会静默失效。
`CaseDataSourceReaper` 是一个定时兜底回收器:当用户会话自然过期、被顶下线或被踢下线时,如果没有对应的登出监听回调,已打开的案件 DuckDB 数据源可能长期占用内存配额。该回收器定期扫描已打开案件,判断归属 token 是否仍有效;若无效且没有业务探针报告“仍在运行”,则关闭数据源并清理对应缓存。它采用保守策略:查询会话状态失败时不释放,宁可多占一点内存也不误关正在使用的数据源。
```mermaid
flowchart TD
Start(["定时任务 reap"]) --> CheckOpen["是否有已打开的案件数据源?"]
CheckOpen -->|否| End(["结束本轮扫描"])
CheckOpen -->|是| Iterate["遍历每个 caseId"]
Iterate --> GetOwner["获取归属 userId 与 ownerToken"]
GetOwner --> SessionAlive{"归属会话是否存活?"}
SessionAlive -->|是| NextCase["下一个 caseId"]
SessionAlive -->|否| HasWork{"是否有在途任务?"}
HasWork -->|是| Skip["跳过回收,等待下一轮"]
HasWork -->|否| Close["关闭案件数据源并清理缓存"]
Close --> NextCase
NextCase -->|还有| Iterate
NextCase -->|无| End
```
**图示来源**
- [DataSourceConfig.java:10-38](file://ai-server/src/main/java/com/zsjz/ai/common/config/DataSourceConfig.java#L10-L38)
- [CaseDataSourceReaper.java:15-125](file://ai-server/src/main/java/com/zsjz/ai/common/datasource/CaseDataSourceReaper.java#L15-L125)
**章节来源**
- [DataSourceConfig.java:10-38](file://ai-server/src/main/java/com/zsjz/ai/common/config/DataSourceConfig.java#L10-L38)
- [CaseDataSourceReaper.java:15-125](file://ai-server/src/main/java/com/zsjz/ai/common/datasource/CaseDataSourceReaper.java#L15-L125)
### Redis 连接与会话依赖
Redis 通过 `spring-boot-starter-data-redis` 自动装配,并在 dev/pro 配置中指定 host、port。Sa-Token 的 Redis Jackson 集成使 Redis 成为登录态的硬依赖:Redis 不可用时 `StpUtil.*` 直接抛异常,没有降级实现。项目中多处使用 `RedisTemplate` 与 `StringRedisTemplate`,包括系统健康检查、缓存管理、登录活动记录、案件数据缓存等。
需要注意:Sa-Token 的生产默认单端登录,后登录会顶掉前登录;联调多端时可传入 `-DSA_TOKEN_CONCURRENT=true` 或通过环境变量覆盖。
**章节来源**
- [application-dev.yaml:1-87](file://ai-server/src/main/resources/application-dev.yaml#L1-L87)
- [application-pro.yaml:1-87](file://ai-server/src/main/resources/application-pro.yaml#L1-L87)
### Agent 工作区与系统目录初始化
`AppLoadEndEventListener` 实现 `CommandLineRunner`,在 Spring 容器启动完成后执行目录初始化与缓存初始化:
- 创建临时目录、系统 RocksDB 目录、许可证目录、Agent 目录、技能目录。
- 初始化全局缓存与系统级 RocksDB 数据。
- 注释说明案件级 `CaseDataCache` 不在启动时预热,因为未开案时 slave 数据源不存在,强行读取会导致启动失败;改为开案后按需加载。
- 初始化 Tower 相关工具。
```mermaid
flowchart TD
Entry(["CommandLineRunner.run"]) --> InitDir["创建系统目录"]
InitDir --> GlobalCache["初始化全局缓存"]
GlobalCache --> RocksDB["初始化系统 RocksDB 数据"]
RocksDB --> CaseCacheNote["暂不预热案件缓存"]
CaseCacheNote --> Tower["初始化 Tower 工具"]
Tower --> Done(["完成"])
```
**图示来源**
- [AppLoadEndEventListener.java:15-58](file://ai-server/src/main/java/com/zsjz/ai/common/event/AppLoadEndEventListener.java#L15-L58)
**章节来源**
- [AppLoadEndEventListener.java:15-58](file://ai-server/src/main/java/com/zsjz/ai/common/event/AppLoadEndEventListener.java#L15-L58)
### 全文检索索引创建
`SearchIndexInitializer` 实现 `ApplicationRunner`,在应用启动时尝试创建 Elasticsearch 全文检索索引。ES 不可用时仅记录错误日志,不阻断启动;索引会在首次写入时由底层服务重试创建。这种设计让全文检索成为增强能力而非启动硬性依赖。
**章节来源**
- [SearchIndexInitializer.java:18-30](file://ai-server/src/main/java/com/zsjz/ai/module/search/service/SearchIndexInitializer.java#L18-L30)
### 智能清洗批次恢复与看门狗
`AiCleanWatchdog` 承担两个职责:
1. **启动恢复**:监听 `ApplicationReadyEvent`,将所有非终态的智能清洗批次标记为 FAILED,原因是虚拟线程不跨进程重启,进程重启后旧 worker 一定已死亡。用户可重新发起清洗,从而形成恢复路径。
2. **运行时看门狗**:扫描长时间无进展的非终态批次,将其标记为 FAILED,以便用户重试。判定逻辑基于 `update_time` 与 `stale-minutes` 配置。
```mermaid
flowchart TD
Startup(["应用就绪"]) --> MarkFailed["将全部非终态批次标为 FAILED"]
MarkFailed --> LogRestart["记录恢复日志"]
Runtime(["定时扫描"]) --> CheckStale{"是否存在超时批次?"}
CheckStale -->|否| WaitNext["等待下一轮"]
CheckStale -->|是| MarkStale["标记为 FAILED 并记录原因"]
MarkStale --> WaitNext
```
**图示来源**
- [AiCleanWatchdog.java:64-95](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanWatchdog.java#L64-L95)
**章节来源**
- [AiCleanWatchdog.java:64-95](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanWatchdog.java#L64-L95)
### 向量索引自举与可用性判断
`AiCleanTemplateVectorIndex` 负责表结构与 AI 模板元数据的向量索引。其启动自举逻辑监听 `ApplicationReadyEvent`:
- 如果向量功能未启用或禁止启动自举,直接返回。
- 如果嵌入模型不可用,只记日志并跳过。
- 如果向量维度无效,跳过。
- 如果向量表存在且有文档,跳过。
- 否则异步执行全量重建。
整个链路遵循 fail-open:向量能力缺失时不阻断主业务,只是降低模板语义召回与 Agent 选表能力。
```mermaid
flowchart TD
Ready(["ApplicationReadyEvent"]) --> Enabled{"向量索引已启用?"}
Enabled -->|否| Exit["退出"]
Enabled -->|是| Available{"嵌入模型可用?"}
Available -->|否| LogUnavailable["记录不可用信息"]
LogUnavailable --> Exit
Available -->|是| Dimensions{"维度有效?"}
Dimensions -->|否| LogBadDimensions["记录维度无效"]
LogBadDimensions --> Exit
Dimensions -->|是| Exists{"向量表存在且有数据?"}
Exists -->|是| Exit
Exists -->|否| RebuildAsync["异步全量重建"]
```
**图示来源**
- [AiCleanTemplateVectorIndex.java:221-260](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/index/AiCleanTemplateVectorIndex.java#L221-L260)
**章节来源**
- [AiCleanTemplateVectorIndex.java:221-260](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/index/AiCleanTemplateVectorIndex.java#L221-L260)
## 依赖关系分析
- **Spring Boot 版本**:父 POM 锁定 `spring-boot-starter-parent:3.5.16`,因此 ai-server 运行于 Spring Boot 3.5 系列。
- **Java 版本**:ai-server 的 `java.version=25`,ONNX Runtime 与 Java 25 配合时可能出现 restricted method 警告,可通过 JVM 参数 `--enable-native-access=ALL-UNNAMED` 消除。
- **数据库**:PostgreSQL 为主数据源,pgvector 用于向量存储;DuckDB 作为每案独立库,通过动态数据源与 `CaseRoutingDataSource` 接入。
- **缓存与会话**:Redis 提供 Sa-Token 会话、全局缓存、登录活动、系统健康检查等能力。
- **检索**:Elasticsearch 提供全文检索;向量检索依赖 pgvector 与嵌入模型(本地 bge-m3 ONNX 或在线 embedding)。
- **Agent 能力**:AgentScope harness 及 DashScope、Ollama、OpenAI 扩展,Mem0、RAG Simple、Redis 扩展。
```mermaid
graph LR
App["App 主类"] --> Spring["Spring Boot 3.5.16"]
Spring --> PostgreSQL["PostgreSQL"]
Spring --> PgVector["pgvector"]
Spring --> DuckDB["DuckDB 案件库"]
Spring --> Redis["Redis"]
Spring --> ES["Elasticsearch"]
Spring --> AgentScope["AgentScope 扩展"]
Spring --> Embedding["本地 bge-m3 / 在线 embedding"]
```
**图示来源**
- [pom.xml:1-23](file://pom.xml#L1-L23)
- [ai-server/pom.xml:1-40](file://ai-server/pom.xml#L1-L40)
- [ai-server/pom.xml:40-200](file://ai-server/pom.xml#L40-L200)
- [application-dev.yaml:1-87](file://ai-server/src/main/resources/application-dev.yaml#L1-L87)
- [application-pro.yaml:1-87](file://ai-server/src/main/resources/application-pro.yaml#L1-L87)
**章节来源**
- [pom.xml:1-23](file://pom.xml#L1-L23)
- [ai-server/pom.xml:1-40](file://ai-server/pom.xml#L1-L40)
- [ai-server/pom.xml:40-200](file://ai-server/pom.xml#L40-L200)
## 性能与启动特性
- **调度线程池**:默认 4 线程,避免 SSE 心跳、数据源回收、AI 清洗看门狗、附件清理等定时任务互相阻塞。
- **上传限制**:HTTP 编解码最大内存、表单最大文件大小与请求大小均可通过环境变量覆盖。
- **DuckDB 预算**:通过 `max-open-cases`、`memory-ratio`、`threads-per-instance` 控制并发案件数与内存占比,防止多人开案叠加资源。
- **向量模型预热**:本地 bge-m3 权重常驻堆外内存约 2.5~3GB,首次加载耗时较长;支持 `eager-load` 在启动时后台预热,也支持懒加载。
- **向量索引自举**:只在索引不存在或为空时触发,避免重复重建;重建过程异步执行并有连续失败熔断。
- **Sa-Token 单端登录**:生产默认后登录顶掉前登录,需要多端联调时通过参数或环境变量开启并发。
[本节为通用性能说明,不直接分析具体代码片段]
## 常见问题排查
### 端口冲突
- **现象**:启动时报端口占用,或前端无法访问后端。
- **定位点**:`server.port=8980`,`server.servlet.context-path=/js/a`。
- **处理建议**:修改端口或停止占用 8980 的进程;注意前端访问路径需包含 `/js/a`。
**章节来源**
- [application.yaml:1-20](file://ai-server/src/main/resources/application.yaml#L1-L20)
### 数据库不可达
- **现象**:启动时报 PostgreSQL 连接失败、驱动异常,或后续 SQL 报连接拒绝。
- **定位点**:dev/pro 中 `spring.datasource.dynamic.primary=master`,`master.url`、`username`、`password`、`driver-class-name`。
- **处理建议**:
- 确认 PostgreSQL 已启动且网络可达。
- 检查 JDBC URL、用户名、密码是否正确。
- 开发环境默认指向内网地址,部署环境需改为实际数据库地址。
- 若使用 pgvector,需确认扩展已安装。
**章节来源**
- [application-dev.yaml:1-40](file://ai-server/src/main/resources/application-dev.yaml#L1-L40)
- [application-pro.yaml:1-40](file://ai-server/src/main/resources/application-pro.yaml#L1-L40)
### Redis 连接失败
- **现象**:Sa-Token 登录失败、会话写入失败、健康检查异常,或直接抛出 Redis 连接异常。
- **定位点**:`spring.data.redis.host`、`spring.data.redis.port`;Sa-Token 依赖 Redis 且无降级实现。
- **处理建议**:
- 确认 Redis 服务已启动且主机端口正确。
- 如部署在容器或云平台,注意网络安全组与内网地址。
- 若只需认证而不需要 Redis 能力,应改造架构;当前版本 Redis 是登录硬依赖。
**章节来源**
- [application-dev.yaml:41-87](file://ai-server/src/main/resources/application-dev.yaml#L41-L87)
- [application-pro.yaml:41-87](file://ai-server/src/main/resources/application-pro.yaml#L41-L87)
### 向量库未启用或向量索引不可用
- **现象**:模板语义召回为空、Agent 搜索不到表结构、AI 模板匹配候选减少。
- **定位点**:
- `zsjz.embedding.enabled`:决定是否使用本地 bge-m3。
- `zsjz.embedding.model-path`:本地模型目录。
- `zsjz.ai-clean.vector.enabled`:向量索引总开关。
- `zsjz.ai-clean.vector.auto-rebuild-on-startup`:启动自举开关。
- pgvector 扩展与 PostgreSQL 向量表。
- **处理建议**:
- 如果使用本地模型,确认模型目录存在且包含所需权重文件。
- 如果切换为在线 embedding,确保 agent_model 中存在活跃类型。
- 检查 `zsjz.ai-clean.vector.enabled` 是否为 true。
- 查看启动日志中是否出现“启动自举跳过模板向量索引”或“向量索引不可用”。
- 必要时手工调用重建接口。
**章节来源**
- [application.yaml:60-140](file://ai-server/src/main/resources/application.yaml#L60-L140)
- [AiCleanTemplateVectorIndex.java:221-260](file://ai-server/src/main/java/com/zsjz/ai/module/aiclean/index/AiCleanTemplateVectorIndex.java#L221-L260)
### Elasticsearch 不可用
- **现象**:启动时报创建索引失败,但应用仍可启动;后续写入时重试创建。
- **定位点**:`SearchIndexInitializer` 捕获异常并记录日志;Elasticsearch 配置在 dev/pro 的 `spring.elasticsearch.uris`。
- **处理建议**:
- 先启动 Elasticsearch。
- 检查 `uris`、连接超时、套接字超时。
- 不要因启动日志报错直接认为应用失败,应观察首次写入行为。
**章节来源**
- [SearchIndexInitializer.java:18-30](file://ai-server/src/main/java/com/zsjz/ai/module/search/service/SearchIndexInitializer.java#L18-L30)
- [application-dev.yaml:41-56](file://ai-server/src/main/resources/application-dev.yaml#L41-L56)
- [application-pro.yaml:41-56](file://ai-server/src/main/resources/application-pro.yaml#L41-L56)
### 启动后案件数据源泄漏
- **现象**:多人开案后无法新建案件,提示达到 DuckDB 最大打开案件数。
- **定位点**:`CaseDataSourceReaper` 定时扫描,依据归属 token 与业务探针决定是否回收。
- **处理建议**:
- 检查 Sa-Token 会话是否正常。
- 检查是否有长任务未结束导致探针认为仍在运行。
- 查看回收日志中的“兜底扫描”行,确认会话存活判断是否符合预期。
**章节来源**
- [CaseDataSourceReaper.java:15-125](file://ai-server/src/main/java/com/zsjz/ai/common/datasource/CaseDataSourceReaper.java#L15-L125)
### 启动目录创建失败
- **现象**:日志出现“初始化系统文件失败”,Agent 工作区、许可证目录或 RocksDB 目录未创建。
- **定位点**:`AppLoadEndEventListener.initDir()`。
- **处理建议**:
- 确认应用进程对目标目录有写权限。
- 确认磁盘空间充足。
- 检查 `PathConst` 指向的路径是否被安全软件或容器卷挂载限制。
**章节来源**
- [AppLoadEndEventListener.java:33-58](file://ai-server/src/main/java/com/zsjz/ai/common/event/AppLoadEndEventListener.java#L33-L58)
## 结论
ai-server 以 `com.zsjz.ai.App` 为唯一应用入口,使用 Spring Boot 3.5.16 与 Java 25,围绕 PostgreSQL、Redis、Elasticsearch、pgvector、DuckDB 与 AgentScope 构建。启动阶段的关键横切能力包括:系统目录与 Agent 工作区初始化、全局缓存与 RocksDB 初始化、全文检索索引幂等创建、智能清洗批次恢复、模板向量索引自举,以及数据源兜底回收。配置通过 `application.yaml` 统一管理业务配置,并通过 `${ENV_NAME:默认值}` 形式支持环境变量覆盖;数据库、Redis、Elasticsearch、存储路径、Sa-Token 与 Neo4j 等环境差异放在 `application-dev.yaml` 与 `application-pro.yaml` 中。常见启动问题主要集中在端口、数据库连通性、Redis 可用性、向量库开关与模型路径、以及案件数据源生命周期管理上。