在高并发场景中,频繁的小请求可能成为系统瓶颈 —— 比如用户详情页需要调用用户服务、订单服务、优惠券服务等多个接口,每个接口单独请求会导致 “网络往返次数过多”“连接数耗尽” 等问题。请求合并与批处理技术,通过将多个小请求合并为一个批量请求,减少网络开销和资源消耗,提升系统整体吞吐量。
请求合并的核心价值
请求合并的核心是 “减少交互次数”,带来的优势:
- 降低网络延迟:一次网络往返处理多个请求,减少 RTT(往返时间)累积
- 减少资源占用:合并后的请求只需建立一次连接,降低服务器的连接数和线程消耗
- 提升下游服务性能:下游服务处理批量请求的效率通常高于多次单条处理(如数据库批量查询比多次单查更快)
主流实现方案
1. 本地请求合并:同一服务内的批量处理
对于同一服务内的多次调用(如循环查询用户信息),通过批量接口替代单条查询。
反例(低效) :
// 循环调用单条查询,产生N次数据库访问
List<Long> userIds = Arrays.asList(1L, 2L, 3L);
List<User> users = new ArrayList<>();
for (Long userId : userIds) {
User user = userMapper.getById(userId); // 单条查询
users.add(user);
}
正例(优化) :
// 批量查询,1次数据库访问
List<Long> userIds = Arrays.asList(1L, 2L, 3L);
List<User> users = userMapper.batchGetByIds(userIds); // 批量查询SQL:SELECT * FROM user WHERE id IN (1,2,3)
接口设计:提供批量查询接口,如POST /users/batch-get,接收 ID 列表,返回用户列表:
// 请求
{ "ids": [1,2,3] }
// 响应
{
"code": 200,
"data": [
{"id":1, "name":"张三"},
{"id":2, "name":"李四"}
]
}
2. 分布式请求合并:基于缓存的延迟合并
在分布式系统中,多个请求同时查询同一批资源(如商品详情),可通过缓存 + 延迟合并减少下游服务压力。
实现逻辑(以商品服务为例) :
-
前端同时请求商品 1001、1002、1003 的详情
-
网关或 API 层收集一定时间内(如 10ms)的相同类型请求
-
将多个单 ID 请求合并为一个批量请求,调用商品服务的
/products/batch-get接口 -
接收批量响应后,拆分结果返回给各请求方
代码简化示例:
// 基于Guava的LoadingCache实现本地缓存+合并查询
private LoadingCache<Long, Product> productCache = CacheBuilder.newBuilder()
.maximumSize(1000)
.build(new CacheLoader<Long, Product>() {
@Override
public Product load(Long productId) {
return productService.getById(productId); // 单条查询( fallback )
}
// 重写批量加载方法
@Override
public Map<Long, Product> loadAll(Iterable<? extends Long> productIds) {
return productService.batchGetByIds(productIds); // 批量查询
}
});
// 获取商品详情(自动触发批量合并)
public Product getProduct(Long productId) {
try {
return productCache.get(productId);
} catch (ExecutionException e) {
throw new RuntimeException("获取商品失败", e);
}
}
适用场景:高频、低延迟要求的查询接口(如商品详情、用户信息),且 ID 分散度不高。
批处理的注意事项
1. 批量大小控制
- 单次批量请求的 ID 数量不宜过多(如控制在 100 以内),避免下游服务处理超时
- 超过上限时自动分片(如 200 个 ID 分 2 次请求)
2. 超时与重试策略
- 批量接口需设置合理的超时时间(比单条接口稍长,但不宜过长)
- 重试需谨慎,避免批量失败后重试导致更大压力,建议部分失败时只重试失败的 ID
3. 一致性保证
- 批量查询应保证与单条查询结果一致(如过滤条件、权限校验)
- 批量更新 / 删除需考虑事务一致性,建议通过分布式事务或补偿机制确保数据正确
避坑指南
-
避免 “为合并而合并”:低频接口或单次请求只查询 1 条数据的场景,合并反而增加复杂度
-
注意缓存一致性:分布式合并查询依赖缓存时,需确保缓存更新机制可靠,避免返回旧数据
-
监控批量接口性能:重点监控批量接口的响应时间、错误率,与单条接口对比,确保优化效果
请求合并与批处理不是 “银弹”,但在高频小请求场景中,它能像 “流量整形” 一样,将零散的请求汇聚成有序的 “数据流”,大幅降低系统的资源消耗 —— 这正是后端优化 “四两拨千斤” 的智慧所在。