通常我们的系统查询过程如下图
当我们面临百万级甚至更过查询请求时,这种简单应用结构明显无法满足业务及性能要求。此时我们需要对上述结构进行优化。通常的做法有一下两种方式
- 负载均衡
将应用后台集群部署,降低单个后台服务器压力。 - 缓存、缓冲
服务层查询数据库时做缓存(Cache/Redis)、缓冲(MQ)
但是上述两种优化方式中百万级别的请求依然会进行百万级别的数据库或者缓存访问。并没有降低服务层服务器、缓存服务器、数据库服务器压力。服务器又无法无限扩张,此时可以通过请求合并的方式进行优化。请求合并是将前端大量的相同内容的请求做一次中转合并,降低服务层以及数据库查询的压力。
优化前
每次前端请求都查询一次数据库
try{
countDownLatch.await();
ReqMerger reqMerger =reqMergerService.queryById(id);
System.out.println("第"+id+"次请求,结果:"+reqMerger);
}catch (Exception ex){
ex.printStackTrace();
}
测试
模拟并发1000个请求
static int THREAD_NUM=1000;
static CountDownLatch countDownLatch=new CountDownLatch(THREAD_NUM);
@ResponseBody
@RequestMapping(value="request/single",method ={
RequestMethod.GET})
@ApiOperation(value = "测试:单次请求", notes = "测试单次请求", response = Result.class)
public void singleRequest(
HttpServletRequest req,
HttpServletResponse resp){
for(int i=0;i<THREAD_NUM;i++){
final int id=i;
Thread thread=new Thread(()->{
try{
countDownLatch.await();
//每次请求都直接通过service获取数据
ReqMerger reqMerger =reqMergerService.queryById(id)<