You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
16 KiB
16 KiB
性能优化
**本文引用的文件** - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)目录
简介
本指南面向应用层面的性能优化,覆盖数据库查询、内存管理、线程池配置、HTTP层优化(压缩、缓存、连接池)、分页查询优化(以 PageConverter 为例)以及 JVM 调优与监控。文档结合代码仓库中的实际实现,给出可落地的策略与最佳实践,并附带可视化图示帮助理解。
项目结构
本项目采用多模块结构:
- crm-app:应用启动入口与全局配置
- crm-auth:认证授权与安全相关能力
- crm-base:通用基础能力(MyBatis-Plus、Redis、工具类、分页转换等)
- crm-file:文件服务(对象存储集成、上传下载、预览)
graph TB
subgraph "应用"
APP["crm-app<br/>启动与配置"]
end
subgraph "认证授权"
AUTH["crm-auth<br/>安全、鉴权、令牌、权限"]
end
subgraph "基础能力"
BASE["crm-base<br/>MyBatis-Plus、Redis、工具类"]
end
subgraph "文件服务"
FILE["crm-file<br/>对象存储、上传下载"]
end
APP --> AUTH
APP --> BASE
APP --> FILE
AUTH --> BASE
FILE --> BASE
图表来源
- CrmAppApplication.java
- application.yml
章节来源
- CrmAppApplication.java
- application.yml
核心组件
- 认证与令牌:JWT 过滤器、令牌服务、安全配置
- 数据访问:MyBatis-Plus 配置、通用 Service 基类
- 缓存:部门树缓存、Redis 配置
- 分页转换:PageConverter 将分页结果转换为统一 DTO
- 文件服务:MinIO 客户端与上传下载流程
章节来源
- SecurityConfig.java
- JwtAuthenticationFilter.java
- TokenService.java
- MybatisPlusConfig.java
- RedisConfig.java
- DeptTreeCache.java
- PageConverter.java
- BaseServiceImpl.java
- FileApiImpl.java
- MinioConfig.java
架构总览
下图展示请求从进入 Spring Security 到数据访问与缓存的关键路径,体现认证、权限、分页与缓存的交互。
sequenceDiagram
participant Client as "客户端"
participant Filter as "JwtAuthenticationFilter"
participant SecCfg as "SecurityConfig"
participant TokenSvc as "TokenService"
participant Svc as "业务服务(BaseServiceImpl)"
participant DB as "数据库(MyBatis-Plus)"
participant Cache as "Redis/本地缓存(DeptTreeCache)"
Client->>Filter : "HTTP 请求(携带Token)"
Filter->>SecCfg : "校验白名单/放行规则"
Filter->>TokenSvc : "解析并验证Token"
TokenSvc-->>Filter : "用户上下文"
Filter-->>Client : "通过或拒绝"
Client->>Svc : "调用分页接口"
Svc->>DB : "分页查询(PageHelper/MP)"
DB-->>Svc : "分页结果"
Svc->>Cache : "可选读取部门树/字典等"
Cache-->>Svc : "缓存命中或未命中"
Svc-->>Client : "返回分页响应"
图表来源
- JwtAuthenticationFilter.java
- SecurityConfig.java
- TokenService.java
- BaseServiceImpl.java
- DeptTreeCache.java
详细组件分析
认证与令牌链路(JWT)
- 过滤器负责拦截请求、提取 Token、校验签名与过期时间,并将用户信息注入上下文
- 令牌服务提供生成、解析、刷新等能力
- 安全配置定义放行路径、异常处理、跨域等
classDiagram
class JwtAuthenticationFilter {
+doFilter(request, response, chain)
-validateToken(token)
-setAuthentication(context)
}
class TokenService {
+generateToken(user)
+parseToken(token)
+refreshToken(token)
-verifySignature(token)
}
class SecurityConfig {
+configure(http)
+permitAllPaths()
+exceptionHandling()
}
JwtAuthenticationFilter --> TokenService : "解析/校验"
JwtAuthenticationFilter --> SecurityConfig : "按规则放行"
图表来源
- JwtAuthenticationFilter.java
- TokenService.java
- SecurityConfig.java
章节来源
- JwtAuthenticationFilter.java
- TokenService.java
- SecurityConfig.java
数据访问与分页(MyBatis-Plus + BaseServiceImpl)
- MyBatis-Plus 提供分页插件与通用 Mapper/Service
- BaseServiceImpl 封装常用 CRUD 与分页逻辑,减少样板代码
- 建议配合索引、只取必要字段、避免 N+1 查询
flowchart TD
Start(["分页请求"]) --> BuildQuery["构建查询条件"]
BuildQuery --> ApplyPagination["应用分页参数"]
ApplyPagination --> ExecuteQuery["执行SQL(仅必要字段)"]
ExecuteQuery --> MapResult["映射为DTO/VO"]
MapResult --> ReturnResp["返回分页结果"]
图表来源
- MybatisPlusConfig.java
- BaseServiceImpl.java
章节来源
- MybatisPlusConfig.java
- BaseServiceImpl.java
分页转换(PageConverter)
- 将数据库分页对象转换为统一的分页 DTO,便于前端消费
- 建议:控制每页大小上限、避免大对象序列化、按需加载关联数据
flowchart TD
In(["原始分页对象"]) --> Validate["校验分页参数"]
Validate --> Convert["字段映射/类型转换"]
Convert --> Enrich["补充元数据(总数/页码)"]
Enrich --> Out(["标准分页响应"])
图表来源
- PageConverter.java
章节来源
- PageConverter.java
缓存(部门树与 Redis)
- 部门树缓存用于高频读场景,降低数据库压力
- Redis 配置用于分布式缓存与会话共享
classDiagram
class DeptTreeCache {
+getDeptTree()
-buildTree(depts)
-refreshIfNeeded()
}
class RedisConfig {
+redisTemplate()
+cacheManager()
}
DeptTreeCache ..> RedisConfig : "可选使用Redis"
图表来源
- DeptTreeCache.java
- RedisConfig.java
章节来源
- DeptTreeCache.java
- RedisConfig.java
文件服务(MinIO)
- MinIO 客户端配置连接池、超时与重试
- FileApiImpl 封装上传、分片、下载与预览流程
sequenceDiagram
participant Client as "客户端"
participant FileApi as "FileApiImpl"
participant Minio as "MinIO客户端"
Client->>FileApi : "上传/下载请求"
FileApi->>Minio : "建立连接/读写对象"
Minio-->>FileApi : "流式响应/状态"
FileApi-->>Client : "返回结果/流"
图表来源
- FileApiImpl.java
- MinioConfig.java
章节来源
- FileApiImpl.java
- MinioConfig.java
依赖关系分析
- 认证模块依赖基础模块(工具、配置)
- 文件模块依赖基础模块(配置、工具)
- 启动模块聚合各功能模块
graph LR
APP["crm-app"] --> AUTH["crm-auth"]
APP --> BASE["crm-base"]
APP --> FILE["crm-file"]
AUTH --> BASE
FILE --> BASE
图表来源
- CrmAppApplication.java
章节来源
- CrmAppApplication.java
性能考量
应用层面优化
- 数据库查询优化
- 精准选择字段,避免 SELECT *
- 合理使用索引,关注慢查询与全表扫描
- 避免 N+1 查询,使用批量查询或 JOIN 替代循环查询
- 分页限制最大页大小,防止超大结果集
- 参考实现位置:MybatisPlusConfig.java、BaseServiceImpl.java
- 内存管理
- 控制对象创建与复用,避免临时大对象
- 合理设置分页大小,减少一次性加载的数据量
- 及时释放资源(流、连接),避免内存泄漏
- 参考实现位置:PageConverter.java
- 线程池配置
- Web 容器线程池:根据 CPU 核数与 IO 比例调整
- 异步任务线程池:区分 CPU 密集与 IO 密集任务
- 队列容量与拒绝策略:避免 OOM 与请求丢失
- 监控指标:活跃线程、队列长度、拒绝次数
HTTP 层面优化
- 响应压缩
- 启用 GZIP 压缩,减少带宽占用
- 对静态资源与 JSON 响应进行压缩
- 缓存策略
- 浏览器缓存:合理设置 Cache-Control、ETag
- 服务端缓存:Redis/本地缓存热点数据(如部门树)
- 参考实现位置:DeptTreeCache.java、RedisConfig.java
- 连接池配置
- 数据库连接池:最小/最大连接数、空闲超时、获取超时
- HTTP 客户端连接池:最大连接数、连接超时、请求超时
- 参考实现位置:application.yml、MinioConfig.java
分页查询优化(以 PageConverter 为例)
- 限制每页大小,避免一次性返回过多数据
- 仅查询必要字段,减少序列化开销
- 对关联数据采用懒加载或分批加载
- 在缓存层命中后直接返回,减少数据库压力
- 参考实现位置:PageConverter.java
JVM 调优建议
- 堆内存配置
- 初始堆与最大堆:根据应用峰值与可用内存设定
- 新生代与老年代比例:默认通常较合理,必要时微调
- GC 策略
- 优先使用 G1GC 或 ZGC(JDK17+),降低停顿时间
- 观察 GC 日志,定位频繁 Full GC 的原因
- 监控指标
- 堆使用率、GC 次数与耗时、线程池活跃度、慢查询数量
- 使用 APM 与 Profiler(Arthas、VisualVM)定位瓶颈
性能测试与瓶颈定位
- 压测工具
- JMeter:模拟并发请求,观察吞吐与延迟
- wrk/ab:HTTP 层快速压测
- 定位技巧
- 开启慢查询日志,分析 SQL 执行计划
- 使用 Arthas 在线诊断方法耗时与锁竞争
- 检查线程栈,识别阻塞点与死锁
- 对比不同分页大小与缓存命中率的影响
故障排查指南
- 常见问题
- 高延迟:检查数据库慢查询、连接池耗尽、GC 停顿
- 内存溢出:排查大对象、未关闭流、缓存无界增长
- 认证失败:检查 Token 签名、过期时间、过滤器链顺序
- 排查步骤
- 查看应用日志与错误堆栈
- 采集 JVM 快照与线程 dump
- 分析数据库执行计划与索引使用情况
- 逐步缩小范围,隔离问题模块
章节来源
- JwtAuthenticationFilter.java
- TokenService.java
- MybatisPlusConfig.java
- RedisConfig.java
结论
通过合理的数据库查询优化、内存与线程池配置、HTTP 层压缩与缓存、以及 JVM 调优与监控,可以显著提升系统吞吐与稳定性。分页查询与缓存是常见瓶颈点,应重点优化。建议在上线前进行压测与性能基线评估,持续监控与迭代优化。
附录
- 关键配置参考
- 应用配置:application.yml
- 认证属性:AuthProperties.java
- 安全配置:SecurityConfig.java
- 数据访问:MybatisPlusConfig.java
- 缓存配置:RedisConfig.java
- 文件服务:MinioConfig.java