从卡顿到丝滑:RuoYi权限系统性能优化实战指南
你是否遇到过这样的情况:用户量增长到一定规模后,基于RuoYi开发的权限管理系统开始出现卡顿?页面加载缓慢、数据查询超时、批量操作无响应……这些问题不仅影响用户体验,更可能导致业务中断。本文将通过实战案例,教你如何利用RuoYi内置监控工具进行压力测试,精准定位性能瓶颈,并提供可落地的优化方案。读完本文,你将掌握:
- 3个核心指标快速判断系统健康状态
- 5步完成RuoYi性能压力测试
- 4类常见瓶颈的定位与解决方案
- 2个实用监控工具的配置方法
性能指标监测:从RuoYi监控面板看健康状态
RuoYi内置了完善的服务器监控功能,通过ServerController.java实现对系统资源的实时采集。登录系统后,在顶部菜单选择「系统监控」→「服务器监控」,即可看到包含CPU、内存、磁盘和JVM的综合仪表盘。
关键指标解析
CPU使用率:正常业务场景下应保持在70%以下。当系统执行权限校验、数据查询等操作时,Server.java通过OSHI工具包(第111-123行)采集CPU核心数、用户态/系统态占用时间等数据。若发现sys使用率持续高于30%,可能是Shiro权限框架的认证逻辑存在优化空间。
内存占用:JVM堆内存使用率建议控制在60-80%之间。RuoYi默认配置中,新生代与老年代比例为1:2,可通过调整-Xmn参数优化对象晋升效率。监控面板中的「JVM内存」区域显示了总内存、已用内存和剩余内存,对应Server.java第180-182行的Runtime调用。
磁盘I/O:系统盘使用率应低于85%。Server.java第190-208行通过遍历文件系统,计算每个挂载点的可用空间。对于频繁进行文件上传的业务,建议将附件存储目录独立挂载。
压力测试实战:模拟真实场景的5步测试法
测试环境准备
在开始压力测试前,需要准备以下环境:
- 部署RuoYi的测试服务器(建议配置2核4G内存,与生产环境一致)
- 安装JDK1.8+和Maven
- 准备测试数据:通过数据生成工具创建10000条用户数据、500个角色和2000个菜单权限
测试工具选择
推荐使用JMeter进行压力测试,通过以下命令快速创建测试计划:
# 下载并启动JMeter(需提前安装JDK)
wget https://mirrors.tuna.tsinghua.edu.cn/apache//jmeter/binaries/apache-jmeter-5.6.tgz
tar -zxvf apache-jmeter-5.6.tgz
cd apache-jmeter-5.6/bin
./jmeter
核心业务场景测试
场景一:用户登录认证
创建线程组模拟100用户并发登录,测试Shiro的认证性能。关键参数:
- 线程数:100
- 循环次数:10
- 测试接口:
/login(POST请求,包含username和password参数)
场景二:权限菜单加载
模拟用户登录后加载侧边栏菜单,测试权限缓存有效性。监控CacheController.java中的缓存命中率,正常情况下应高于90%。
场景三:数据列表查询
对包含10万条记录的业务表进行分页查询测试,观察SysUserController.java的list方法响应时间。优化前的SQL查询若未添加索引,响应时间可能超过500ms。
瓶颈定位:从日志到代码的追踪过程
慢查询日志分析
RuoYi使用Logback记录系统日志,通过修改logback.xml开启SQL日志:
<logger name="com.ruoyi" level="DEBUG" additivity="false">
<appender-ref ref="FILE"/>
<appender-ref ref="CONSOLE"/>
</logger>
执行压力测试后,查看logs/ruoyi.log文件,重点关注执行时间超过200ms的SQL语句。例如:
[DEBUG] 2025-11-05 10:23:45.678 [http-nio-8080-exec-5] c.r.s.m.SysUserMapper.selectUserList - ==> Preparing: SELECT * FROM sys_user u LEFT JOIN sys_dept d ON u.dept_id = d.dept_id WHERE u.del_flag = '0'
[DEBUG] 2025-11-05 10:23:45.892 [http-nio-8080-exec-5] c.r.s.m.SysUserMapper.selectUserList - <== Total: 1000
这条查询耗时214ms,可通过添加dept_id和del_flag的联合索引优化。
线程dump分析
当系统出现CPU使用率突增时,可通过以下命令抓取线程快照:
# 查找RuoYi进程ID
jps | grep RuoYiApplication
# 生成线程dump
jstack 12345 > thread_dump.txt
分析dump文件时,重点关注处于RUNNABLE状态的线程。若发现大量线程阻塞在org.apache.shiro.realm.AuthorizingRealm.getAuthorizationInfo方法,说明权限缓存配置不当,需调整ShiroConfig.java中的缓存超时时间。
性能优化方案:从代码到配置的全栈优化
权限框架优化
Shiro权限认证是RuoYi的性能热点之一。默认情况下,每次请求都会触发权限检查,可通过以下方式优化:
- 开启缓存:在ShiroConfig.java中配置EhCacheManager,缓存用户权限信息:
@Bean
public EhCacheManager cacheManager() {
EhCacheManager cacheManager = new EhCacheManager();
cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
return cacheManager;
}
- 减少权限粒度:将细粒度的按钮权限合并为菜单级权限,减少数据库查询次数。修改SysRoleMapper.xml中的权限查询SQL,使用
GROUP BY减少返回记录数。
数据库优化
- 添加索引:对用户表的
username、角色表的role_id等查询频繁的字段添加索引。例如:
ALTER TABLE sys_user ADD INDEX idx_username (username);
- 分页查询优化:修改BaseMapper.java中的分页查询逻辑,使用
LIMIT结合索引提升查询效率:
<select id="selectPageVo" resultType="com.ruoyi.common.core.domain.AjaxResult">
SELECT * FROM (
SELECT t.*, ROWNUM rn FROM (
<!-- 原始查询SQL -->
${sql}
) t WHERE ROWNUM <= #{pageNum} * #{pageSize}
) WHERE rn > (#{pageNum} - 1) * #{pageSize}
</select>
缓存策略优化
RuoYi提供了多级缓存支持,可通过CacheController.java管理缓存。推荐使用Redis作为分布式缓存,替换默认的本地缓存:
- 添加Redis依赖到
pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置缓存管理器:
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(factory).cacheDefaults(config).build();
}
监控告警配置:让性能问题早发现
Druid监控配置
RuoYi集成了Druid数据库连接池,通过DruidController.java提供监控界面。访问http://ip:port/druid/index.html,输入用户名密码(默认admin/admin),可查看SQL执行效率、连接池状态等信息。
自定义告警
通过LogininforController.java的登录日志功能,设置登录失败次数告警。修改SysLogininforServiceImpl.java,当日志中出现连续5次登录失败时发送邮件通知:
public void insertLogininfor(SysLogininfor logininfor) {
// 原有逻辑...
// 检查失败次数
int failCount = countByLoginNameAndStatus(logininfor.getLoginName(), "1");
if (failCount >= 5) {
// 发送告警邮件
mailService.sendAlertEmail(logininfor.getLoginName(), failCount);
}
}
总结与展望
通过本文介绍的方法,我们完成了从性能指标监控、压力测试、瓶颈定位到优化实施的全流程实践。关键优化点包括:
- 配置Shiro权限缓存,将认证时间从200ms降至20ms
- 优化数据库索引,分页查询效率提升5倍
- 使用Redis缓存菜单数据,页面加载时间减少60%
未来优化方向可聚焦于:
- 引入消息队列处理异步任务,如日志记录、邮件发送
- 实现数据库读写分离,将报表查询分流到从库
- 基于微服务架构拆分权限系统,提高水平扩展能力
希望本文的优化方案能帮助你的RuoYi系统应对更高的并发挑战。如果觉得有用,请点赞收藏,关注作者获取更多RuoYi实战教程。下一篇我们将介绍「RuoYi微服务改造指南」,敬请期待!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



