java 请求过多怎么处理_同时处理多请求

在工作中遇到同时向多个服务请求的场景,在此将自己的研究过程记录一下

模拟三个请求requestA、requestB、requestC:

@Servicepublic classParallelService {publicString requestA() {try{

TimeUnit.MILLISECONDS.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}return "A";

}publicString requestB() {try{

TimeUnit.MILLISECONDS.sleep(2000);

}catch(InterruptedException e) {

e.printStackTrace();

}return "B";

}publicString requestC() {try{

TimeUnit.MILLISECONDS.sleep(2500);

}catch(InterruptedException e) {

e.printStackTrace();

}return "C";

}

}

建立一个测试类ParallelController,request方法用来模拟请求不同服务:

@Slf4j

@RestController

@RequestMapping("parallel")public classParallelController {

@AutowiredprivateParallelService parallelService;private String request(intindex) {if (index == 0) {returnparallelService.requestA();

}if (index == 1) {returnparallelService.requestB();

}if (index == 2) {returnparallelService.requestC();

}return null;

}

}

接下来,就开始尝试不同的请求方式:

串行(传统方式)

/**

* 串行(传统请求)*/@GetMapping("/test1")public voidtest1() {long start =System.currentTimeMillis();

List list = new ArrayList<>();

IntStream.range(0, 3).forEach(index ->{

list.add(request(index));

});

log.info("串行,响应结果:{},响应时长:{}", Arrays.toString(list.toArray()), System.currentTimeMillis() -start);

}

使用JMeter进行压测,压测参数如下:

f0cc4940891613456925efc2f5c34222.png

创建30个线程,在20秒之内循环请求,结果:

ce77f52f4af160194371bb7c386dc04d.png

121d03fe2240d9b0a244e611092f1213.png

从控制台结果可以看到:请求是顺序执行,所以结果都是[A, B, C],响应时长也很稳定

从JMeter结果可以看到:平均响应时长:5805ms,最小响应时长:5507ms,最大响应时长:6497ms,TPS:5.0/sec

并行

并行采用的是java8的语法流,利用多核处理器同时去请求,当获取所有请求结果后才终止

/**

* 并行请求*/@GetMapping("/test2")public voidtest2() {long start =System.currentTimeMillis();

List list = new ArrayList<>();

IntStream.range(0, 3).parallel().forEach(index ->{

list.add(request(index));

});

log.info("java8并行,响应结果:{},响应时长:{}", Arrays.toString(list.toArray()), System.currentTimeMillis() -start);

}

使用jmeter同样的参数压测,结果:

62a9d73fe7a68fdcfe9af4ebe98dcb30.png

60aa128314b650081923654591676f20.png

从控制台结果可以看到:请求是独立执行没有顺序,所以结果是不确定的,响应时长很不稳定

从JMeter结果可以看到:平均响应时长:16648ms,最小响应时长:2513ms,最大响应时长:36052ms,TPS:1.3/sec

多线程

多线程的处理方式是,创建多个线程,分别去请求,当获取所有请求结果后才终止

/**

* 多线程请求*/@GetMapping("/test3")public voidtest3() {long start =System.currentTimeMillis();

List list = new ArrayList<>();

List> futureList = new ArrayList<>();

ExecutorService executor= Executors.newFixedThreadPool(3); //开启3个线程

IntStream.range(0, 3).forEach(index ->{

Future task = executor.submit(() ->request(index));

futureList.add(task);

});for (Futurefuture : futureList) {try{//如果任务执行完成,future.get()方法会返回Callable任务的执行结果。//future.get()方法会产生阻塞,所有线程都阻塞在这里,当获取到一个结果后,才执行下一个

list.add(future.get());

}catch(Exception e) {

log.error(e.getMessage(), e);

}

}//停止接收新任务,原来的任务继续执行

executor.shutdown();

log.info("多线程,响应结果:{},响应时长:{}", Arrays.toString(list.toArray()), System.currentTimeMillis() -start);

}

4c88d7b7772da5bb48a9d997371fd7c6.png

d9f42f01f5479f7fc0cdbf542ded1e50.png

从控制台结果可以看到:请求是顺序执行的,结果都是[A, B, C],响应时长比较稳定

从JMeter结果可以看到:平均响应时长:2505ms,最小响应时长:2503ms,最大响应时长:2519,TPS:11.4/sec

结论:

1、串行处理多请求,代码很简单,响应时长是每个请求时长的总和,很稳定但是效率不高

2、使用java8并行处理,代码很简单,响应时长很不稳定,效率也不高,不建议使用

3、使用多线程处理时,代码复杂,响应时长为单个请求中时长最长的那个,效率很高,推荐使用


版权声明:本文为weixin_29735807原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。