Spring Boot高并发接口优化实战:从线程模型到缓存设计

高并发接口为什么慢

接口响应慢通常不是单一原因,而是请求链路里某个环节成为瓶颈:数据库查询慢、下游服务响应慢、线程池排队、或者锁竞争。优化前先用量化数据定位,压测工具(wrk、JMeter)跑出QPS、P99延迟、线程池活跃数,再对照APM链路追踪找出耗时最高的调用。盲目加缓存或改线程池参数,往往解决不了真正的问题。

线程池配置与服务端线程模型

Tomcat默认线程池200,DB连接池HikariCP默认10。当并发请求超过线程数时,请求进入队列等待,QPS不升反降。线程池大小的经验公式:线程数 = CPU核数 × (1 + 等待时间 / 计算时间)。IO密集型的服务,等待时间占比高,线程数要放宽;纯计算服务,线程数接近核数即可。

server:
  tomcat:
    threads:
      max: 400
      min-spare: 50
    accept-count: 500
    max-connections: 10000

spring:
  datasource:
    hikari:
      maximum-pool-size: 40

线程池调大不是万能的:数据库连接池跟不上,接口照样堵在等待连接。两个池要联动调整,并用压测验证整体吞吐曲线。

缓存设计:Redis与本地缓存的搭配

高并发接口第一优先用缓存扛住读流量。Redis适合跨节点共享的缓存,本地缓存(Caffeine)适合单机高频访问。两级缓存策略:先查本地缓存,未命中再查Redis,最后回源数据库,回源后写回两级缓存。

public Product getProduct(Long id) {
    // 一级:本地缓存
    Product p = localCache.get(id);
    if (p != null) return p;
    // 二级:Redis
    String json = redis.get("product:" + id);
    if (json != null) {
        Product prod = JsonUtil.parse(json);
        localCache.put(id, prod);
        return prod;
    }
    // 三级:数据库
    Product prod = productMapper.selectById(id);
    if (prod != null) {
        redis.set("product:" + id, JsonUtil.toJson(prod), Duration.ofMinutes(30));
        localCache.put(id, prod);
    }
    return prod;
}

缓存的核心问题是缓存击穿、穿透、雪崩。击穿用互斥锁+热点key重建;穿透用布隆过滤器拦截不存在key;雪崩用过期时间加随机抖动,避免大批key同时失效。没有缓存的直接回源,会把流量放大到数据库上。

接口性能的常规优化点

能异步的不要同步。非核心链路(日志、通知、埋点)用消息队列或异步线程池执行,不让它们拖慢主链路。减少N+1查询,批量查询用IN一次性取数。减少序列化开销,Gson、Jackson的默认配置在热路径上会有明显开销,必要时用Fastjson2或手动序列化。响应体过大时压缩或裁剪字段,网络传输时间在高并发下会被放大。

压测与调优的闭环

上线前用wrk做固定并发压测:

wrk -t8 -c200 -d60s http://localhost:8080/api/order/detail

观察压测报告的QPS、延迟分位数和错误率。QPS不达标时,逐层排查是线程池排队、DB慢查询还是第三方依赖拖后腿,修改后重新压测对比。每次优化保留基线数据,避免改完看不出效果。高并发优化是一个测量-定位-调整的循环,每一步都有数据支撑。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springboot-gao-bing-fa-jie-kou-you-hua-shi-zhan-cong-xian/

(0)
小编小编
上一篇 3小时前
下一篇 3小时前

相关推荐