在做互联网医院系统时,很多团队一开始关注的是功能是否完整:AI问诊、智能分诊、医生接诊、电子处方、在线支付。但真正决定系统“能不能扛得住”的,是高并发场景下的性能设计。
尤其是AI问诊模块,一旦推广到多医院、多科室、多城市,用户同时在线发起问诊请求,系统就会面临:
- 瞬时高并发请求
- 大模型推理耗时长
- 数据库读写频繁
- 会话上下文存储压力大
- 处方、订单等核心数据一致性要求高
如果架构设计不到位,系统不是卡顿,就是直接崩溃。
下面我们从架构层、服务层、数据层和AI调用层,系统讲清楚优化思路,并结合代码示例说明实现方式。
一、整体架构思路:从单体到分层解耦
高并发场景下,第一步不是“优化代码”,而是做架构拆分。
推荐结构:
- 网关层(API Gateway)
- 业务服务层(问诊、分诊、订单、处方)
- AI推理服务层(独立部署)
- 缓存层(Redis)
- 消息队列(MQ)
- 数据存储层(MySQL + 分库分表)
1. 接入层限流(防止系统被打爆)
使用Spring Boot + Redis做令牌桶限流:
@Component
public class RateLimitInterceptor implements HandlerInterceptor {
@Autowired
private StringRedisTemplate redisTemplate;
private static final int LIMIT = 100; // 每秒100次
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String key = "ai:rate:limit";
Long count = redisTemplate.opsForValue().increment(key);
if (count == 1) {
redisTemplate.expire(key, 1, TimeUnit.SECONDS);
}
if (count > LIMIT) {
response.setStatus(429);
response.getWriter().write("Too Many Requests");
return false;
}
return true;
}
}
意义很明确:
宁可丢弃部分请求,也不能让系统整体雪崩。
二、AI问诊服务异步化(避免阻塞)
大模型推理时间往往在1–5秒之间,如果直接同步调用,线程会被大量占用。
解决方案:
使用消息队列 + 异步回调。
1. 请求入队
@PostMapping("/ai/consult")
public String consult(@RequestBody ConsultRequest request) {
String taskId = UUID.randomUUID().toString();
request.setTaskId(taskId);
rabbitTemplate.convertAndSend("ai.exchange",
"ai.routing",
request);
return taskId;
}
2. 消费端处理AI推理
@RabbitListener(queues = "ai.queue")
public void handleConsult(ConsultRequest request) {
String result = aiService.callModel(request.getContent());
redisTemplate.opsForValue().set(
"ai:result:" + request.getTaskId(),
result,
10,
TimeUnit.MINUTES
);
}
3. 前端轮询获取结果
@GetMapping("/ai/result/{taskId}")
public String getResult(@PathVariable String taskId) {
return redisTemplate.opsForValue()
.get("ai:result:" + taskId);
}
这样做的好处:
- 主线程快速释放
- AI计算压力可横向扩展
- 系统吞吐能力大幅提升
三、数据库层优化:分库分表 + 索引优化
AI问诊的聊天记录、问诊记录数据量极大。
1. 聊天记录按用户ID分表
CREATE TABLE consult_record_0 LIKE consult_record;
CREATE TABLE consult_record_1 LIKE consult_record;
...
CREATE TABLE consult_record_15 LIKE consult_record;
分表逻辑:
public String getTableName(Long userId) {
int index = (int)(userId % 16);
return "consult_record_" + index;
}
2. 添加核心索引
CREATE INDEX idx_user_id ON consult_record(user_id);
CREATE INDEX idx_create_time ON consult_record(create_time);
避免全表扫描,是高并发系统最基础的保障。
四、缓存策略:减少数据库压力
在互联网医院AI问诊中,有三类数据可以缓存:
- 常见问答知识库
- 医生排班信息
- 热门科室信息
示例:缓存医生信息
public Doctor getDoctor(Long doctorId) {
String key = "doctor:" + doctorId;
String json = redisTemplate.opsForValue().get(key);
if (json != null) {
return JSON.parseObject(json, Doctor.class);
}
Doctor doctor = doctorMapper.selectById(doctorId);
redisTemplate.opsForValue().set(
key,
JSON.toJSONString(doctor),
30,
TimeUnit.MINUTES
);
return doctor;
}
在高并发下,这种缓存机制可以减少70%以上数据库访问。
五、线程池优化:避免线程爆炸
AI问诊如果使用默认线程池,很容易耗尽资源。
建议自定义线程池:
@Bean
public ExecutorService aiExecutor() {
return new ThreadPoolExecutor(
10,
50,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
关键点:
- 核心线程数控制
- 队列大小限制
- 拒绝策略必须可控
六、读写分离 + 主从数据库
当问诊记录写入量大时,可以采用:
- 主库写入
- 从库读取历史数据
示意配置:
spring:
datasource:
dynamic:
primary: master
datasource:
master:
url: jdbc:mysql://master-db:3306/hospital
slave:
url: jdbc:mysql://slave-db:3306/hospital
这样能显著提升系统整体吞吐能力。
七、AI模型服务独立部署
不要把AI推理和主业务部署在同一服务。
推荐:
- Docker独立部署推理服务
- GPU服务单独扩容
- Kubernetes做自动伸缩
示例部署配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-service
spec:
replicas: 3
template:
spec:
containers:
- name: ai
image: ai-model:latest
resources:
limits:
nvidia.com/gpu: 1
这样可以做到:
- AI压力独立扩容
- 主业务稳定运行
- 弹性应对峰值问诊
八、核心结论
在互联网医院AI问诊场景下,高并发优化的本质是:
- 架构解耦
- 异步化处理
- 缓存前置
- 数据拆分
- 服务独立扩容
不要试图用“优化几行代码”解决性能问题。
真正的高并发系统,拼的是架构设计能力。
如果你的系统未来要支撑:
- 多医院接入
- 多城市运营
- 大规模用户问诊
- 7×24小时在线
那么高并发优化必须从一开始就纳入架构设计,而不是等崩溃之后再补救。
真正成熟的互联网医院AI问诊系统,一定是为峰值流量而设计的,而不是为日常流量而设计的。