高并发场景下的真实痛点
公司上午九点,全员准时打卡、开晨会、刷新项目管理系统。突然,系统卡住,提交个报销单要等半分钟,页面还时不时报错。这种场景在中小型企业里太常见了。背后往往不是服务器扛不住,而是多个框架集成时没做好优化。
很多办公系统用的是 Spring Boot 做主干,集成了 Redis 做缓存、RabbitMQ 处理异步任务、再加个 Shiro 做权限控制。单独看每个组件都挺稳,但一到上班高峰期,请求一涌而上,系统就开始抽风。
连接池配置不当,最先拖后腿
最常见的问题是数据库连接池设得太小。比如 HikariCP 默认最大连接数只有 10,面对几百人同时操作,光排队等连接就得耗掉几百毫秒。这时候哪怕 SQL 执行很快,整体响应也慢。
合理的做法是根据并发量调整:
spring.datasource.hikari.maximum-pool-size=50
spring.datasource.hikari.connection-timeout=3000
spring.datasource.hikari.idle-timeout=600000把最大连接数提到 50,超时时间拉长,避免频繁创建销毁连接。实测下来,接口平均响应时间能从 800ms 降到 200ms 左右。
缓存穿透和雪崩不能靠运气防
Redis 用得好能救命,用不好反而添乱。比如某个用户信息缓存失效的瞬间,上千请求直接打到数据库,瞬间就把 MySQL 拖垮了。这就是典型的缓存雪崩。
加随机过期时间是最简单的应对方式:
Long ttl = 300 + new Random().nextInt(300); // 5~10分钟
redisTemplate.opsForValue().set(key, value, ttl, TimeUnit.SECONDS);另外,对不存在的数据也做空值缓存,避免反复查库。虽然多占点内存,但换来了稳定性,值得。
异步解耦,别让通知拖慢主流程
审批通过后发邮件、短信、站内信,这些操作全放在主线程里同步执行,用户就得等着。其实完全可以用消息队列切出去。
比如用 RabbitMQ 改造一下:
@RabbitListener(queues = "notify.queue")
public void handleNotification(NotificationMessage msg) {
mailService.send(msg.getTo(), msg.getContent());
smsService.send(msg.getPhone(), msg.getContent());
}主业务逻辑只负责把消息扔进队列,几毫秒就完事。后续通知由消费者慢慢处理,既不耽误用户体验,又能削峰填谷。
接口限流,保护系统不过载
总有那么几个同事喜欢疯狂刷新页面,或者误触导致重复提交。这时候没有限流机制,系统很容易被自己人搞崩。
用 Sentinel 加个简单规则就行:
FlowRule rule = new FlowRule();
rule.setResource("/api/submit");
rule.setCount(10); // 每秒最多10次
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
FlowRuleManager.loadRules(Collections.singletonList(rule));超过阈值就快速失败,前端弹个提示就好。看似限制了操作,其实是保护了所有人。
高并发不是大厂专属问题。只要办公系统在线,就有面临流量压力的一天。框架集成不是拼乐高,接上就行。每个组件之间的协作方式,才是真正决定系统是否流畅的关键。