并发问题解决

一、@Autowired 注入解决 每次创建新对象、内存暴涨、性能差

Spring 管理的 Bean 默认都是全局唯一一个的单例

**以前:**每次请求都 new ObjectMapper ()→ 1000 个请求 = 1000 个对象→ 内存暴涨、GC 频繁、性能差、并发不安全

现在:@Autowired 直接注入 Spring 创建好的单例→ 整个项目永远只有 1 个 ObjectMapper→ 所有请求共用这一个→ 不占额外内存、不重复创建、性能极高、并发安全

总结:@Autowired = 拿全局唯一对象new = 每次都造新对象


二、连接池解决OkHttp 并发崩溃问题

**问题原因:**无连接池,频繁创建销毁连接,高并发下直接卡死。

java 复制代码
private final OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)   // 连接最多等30秒
        .readTimeout(120, TimeUnit.SECONDS)    // 读数据最多等120秒
        .writeTimeout(30, TimeUnit.SECONDS)     // 发数据最多等30秒
        .connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)) // 连接池
        .build();

连接池

**以前:**每次请求都新建连接 → 用完关闭

**现在:**建立连接后不扔,放池子里复用→ 高并发不卡顿、不崩溃、速度飞快

超时时间 : 防止 AI 响应太慢把接口卡死**,**到时间自动断开,不卡死服务

最大空闲连接数 = 10 连接存活时间 = 5 分钟

总结:给 AI 请求加了 "高速通道 + 连接复用 + 防卡死"高并发必备


三、同步架构

bash 复制代码
主线程 → 调用AI → 等待10秒 → AI返回 → 更新数据库 → 返回前端

整个 10 秒,主线程完全卡死

100 人同时访问 → 100 个线程卡死

服务器线程耗尽 → 服务崩溃


四、异步 + 后端自旋架构

bash 复制代码
主线程:
1. 开启异步子线程 → 去调用AI(主线程不管它)
2. 主线程只做一件事:**每隔50ms查一下数据库**
3. 查到完成 → 返回前端

主线程虽然在等待,但它不阻塞任何系统资源

  • 不占用 AI 连接
  • 不占用数据库连接
  • 不阻塞任何外部服务
  • 它只是空循环 + 极轻量查询
  • 每次查询耗时 < 1ms

同步:主线程在等 IO、等网络、等 AI → 卡死资源

异步:主线程只等数据库状态,每次查询 1ms,完全不耗资源AI 任务依然在异步线程里高效执行


五、同步模式

流程:

  1. 用户请求进来,Tomcat 主线程(业务工作线程) 接手
  2. 主线程直接调用 Coze 大模型接口
  3. 卡死 5~15 秒 一动不动,全程占用这个 Tomcat 工作线程
  4. AI 返回→更新数据库→最后响应前端

关键致命点:

  • Tomcat 工作线程池数量有限(默认就几十条)
  • 一条 AI 请求 = 永久占用 1 条核心业务线程 10 秒 +
  • 并发一高:线程全部被 AI 卡死 → 新请求排队、超时、服务雪崩
    这就是并发低的根源:核心业务线程被慢 IO 锁死

六、纯异步模式@Async 子线程干活

流程:

  1. Tomcat 主线程 接收请求、保存初始消息
  2. 开启独立异步子线程去调用 AI、跑耗时逻辑
  3. 主线程直接释放、立刻归还线程池,去接待下一个用户
  4. 子线程慢慢跑 AI,跑完自己更新数据库

优势:

  • 耗时、阻塞、慢 IO 全部丢给异步线程池
  • Tomcat 核心业务线程秒释放,无限接新请求
  • 两套线程池分工:
    • Tomcat 线程:只处理极速短逻辑
    • Async 异步线程:专门扛慢接口、长耗时任务

七、异步 + 主线程轻量自旋

流程:

  1. Tomcat 主线程:存初始消息 → 开启异步子线程跑 AI
  2. 主线程不销毁,每隔 50ms 查一次数据库,极轻量
  3. AI 跑完、状态变更,主线程立刻返回结果

重点回答你:会不会退化同步?

轻微占用主线程,但和「同步阻塞 AI」完全不是一个量级:

  1. 同步:线程卡在网络 IO 等待,重量级阻塞,全程卡死
  2. 自旋:线程只是sleep(50) + 单条数据库简单查询
    • sleepCPU 不占用、挂起休眠
    • 单次 DB 查询极快,毫秒级结束
  3. 真正耗时的网络请求、大模型解析、流处理 ,依然全部在异步子线程

八、主线程 VS 异步子线程 核心区别

1. 线程池不一样

主线程:Tomcat 容器核心业务线程池,容量小、不能堵

子线程:自定义 Async 线程池,专门设计用来扛长耗时任务,容量可以调大

2.阻塞的内容不一样

主线程同步:阻塞在外网 HTTP 长连接、大模型 IO(最重)

异步子线程:专门承接这类重型阻塞

自旋主线程:只阻塞在短暂休眠 + 轻量 DB 查询(最轻)

3.职责拆分

主线程:负责快速接收、快速响应、流量入口

子线程:负责耗时计算、第三方接口、慢任务


九、解答你的终极疑问

疑问 1:都有线程在干活,凭什么异步并发更高?

  • 同步:稀缺的核心业务线程 被慢任务占死
  • 异步:廉价扩容的异步线程 扛慢任务,核心线程自由

不是 "没人干活",是干活的人换了一批、分工合理了


疑问 2:自旋等待,主线程不还是被占用了吗?

是占用,但属于低资源占用

  • 大部分时间在 Thread.sleep,CPU 几乎 0 消耗
  • 没有占用外网连接、没有阻塞 IO、没有卡死第三方请求
  • 对比直接卡 10 秒 AI 网络阻塞,压力下降 90% 以上

疑问 3:资源都在消耗,高并发优势在哪?

高并发的本质:不让「有限的入口线程」被慢任务锁死

  • 同步:10 个慢请求 = 10 个入口线程报废,系统直接堵死
  • 异步 + 自旋:10 个慢请求 = 10 个子线程扛压,入口线程还能继续接几百个新请求

十、极简总结

  1. 主线程为 Tomcat 核心业务线程,数量有限,负责快速处理请求,不能被长耗时第三方接口阻塞;异步子线程由独立线程池管理,专门承载大模型调用等慢任务,实现职责拆分。

  2. 同步方案中,主线程全程阻塞在 AI 网络请求,会快速耗尽业务线程池,导致并发能力极低。

  3. 异步方案将耗时逻辑下放至子线程,核心主线程快速释放,大幅提升系统吞吐与并发承载能力。

  4. 后期为解决前端转圈,增加主线程轻量自旋等待:线程大部分时间休眠,仅做轻量数据库查询,没有重型 IO 阻塞,不会退化為同步性能,既保留异步高并发架构,又实现同步交互体验。

  5. 高并发的核心不是不用线程,而是稀缺入口线程不阻塞、慢任务隔离到独立线程池

总结:异步子线程执行耗时严重的 AI 网络请求,Tomcat主线程负责轻量单条库表轮询任务状态,该方案不会退化为同步模式,核心耗时压力依旧隔离在异步线程池,既保留异步高并发优势,又无需改造前端,解决了页面长时间转圈的问题。

相关推荐
聆风吟º1 小时前
【C标准库】深入理解C语言strcat函数:字符串拼接的利器
c语言·开发语言·strcat·库函数
马优晨1 小时前
oracle 的 Schema
数据库·oracle·oracle的schema·数据库的 schema·oracle的schema数据
带娃的IT创业者1 小时前
深度解析:从零构建高性能 LLM API 中转网关与成本优化实战
开发语言·gpt·llm·php·高性能·成本优化·api网关
老王以为1 小时前
前端视角下的 Java
java·javascript·程序员
看腻了那片水1 小时前
开源一个对业务代码零侵入的透明数据治理框架 —— 【sangsang】
java·mybatis
TechWayfarer1 小时前
IP归属地运营商能解决什么问题?风控/增长/数据平台落地实践(附API代码)
开发语言·网络·python·网络协议·tcp/ip
Nyarlathotep01132 小时前
JUC工具(3):StampedLock的基础和原理
java·后端
gmaajt2 小时前
JavaScript中闭包对垃圾回收器GC标记清除算法的影响
jvm·数据库·python