# 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 可用性、向量库开关与模型路径、以及案件数据源生命周期管理上。