どこ記録のプロセスについての彼の研究、仕事で複数のサービス要求のシーンに同時に満たさ
アナログ3つの要求requestA、requestB、requestC:
@Service パブリック クラスParallelService { パブリック文字列requestA(){ 試みる{ TimeUnit.MILLISECONDS.sleep(1000 )。 } キャッチ(InterruptedExceptionある電子){ e.printStackTrace(); } 戻り 「A 」。 } パブリック文字列requestB(){ 試みる{ TimeUnit.MILLISECONDS.sleep(2000 )。 } キャッチ(InterruptedExceptionある電子){ e.printStackTrace(); } リターン " B " ; } パブリック文字列requestC(){ 試みる{ TimeUnit.MILLISECONDS.sleep(2500 )。 } キャッチ(InterruptedExceptionある電子){ e.printStackTrace(); } 戻り 「C 」。 } }
テストクラスParallelControllerの確立、リクエストメソッドは、別のサービスリクエストをシミュレートするために使用されます。
@ SLF4J
@RestController @RequestMapping(" 平行" ) パブリック クラスParallelController { @Autowired プライベートParallelService parallelService。 プライベート列要求(int型のインデックス){ 場合(インデックス== 0 ){ 戻りparallelService.requestAを(); } 場合(インデックス== 1 ){ 戻りparallelService.requestBを(); } 場合(インデックス== 2 ){ リターンparallelService.requestC(); } 戻り ヌル。 } }
その後、彼らが要求するさまざまな方法を試して始めます。
シリアル(伝統的な方法)
/ * * *シリアル(伝統的な要求) * / @GetMapping(" / TEST1 " ) 公共 ボイドTEST1(){ ロングスタート= にSystem.currentTimeMillis(); リスト <文字列>一覧= 新しい新しいのArrayList <> (); IntStream。範囲(0、3).forEach(インデックス- > { List.add(要求(インデックス)); }); log.info(" シリアル応答結果:{}、長い応答:{} "、Arrays.toStringの(List.toArray())のSystem.currentTimeMillis() - スタート); }
次のように圧力測定のためのJMeterを使用して、圧力測定パラメータは次のとおりです。
30スレッド、20秒以内にサイクル要求、結果を作成します。
結果はコンソールから見ることができる:要求が順次行われ、結果は[A、B、C]であり、非常に安定した長い応答
JMeterは結果から分かる:応答の平均持続時間:5805ms、応答の最小長さ:5507ms、応答の最大長さ:6497ms、 QPS:5.0 /秒
パラレル
平行流java8構文は、マルチコアプロセッサの使用を同時に要求するために、使用される場合、終了後にすべての結果を取得要求
/** * 并行请求 */ @GetMapping("/test2") public void test2() { long start = System.currentTimeMillis(); List<String> 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同样的参数压测,结果:
从控制台结果可以看到:请求是独立执行没有顺序,所以结果是不确定的,响应时长很不稳定
从JMeter结果可以看到:平均响应时长:16648ms,最小响应时长:2513ms,最大响应时长:36052ms,QPS:1.3/sec
多线程
多线程的处理方式是,创建多个线程,分别去请求,当获取所有请求结果后才终止
/** * 多线程请求 */ @GetMapping("/test3") public void test3() { long start = System.currentTimeMillis(); List<String> list = new ArrayList<>(); List<Future<String>> futureList = new ArrayList<>(); ExecutorService executor = Executors.newFixedThreadPool(3); // 开启3个线程 IntStream.range(0, 3).forEach(index -> { Future<String> task = executor.submit(() -> request(index)); futureList.add(task); }); for (Future<String> future : 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); }
从控制台结果可以看到:请求是顺序执行的,结果都是[A, B, C],响应时长比较稳定
从JMeter结果可以看到:平均响应时长:2505ms,最小响应时长:2503ms,最大响应时长:2519,QPS:11.4/sec
结论:
1、串行处理多请求,代码很简单,响应时长是每个请求时长的总和,很稳定但是效率不高
2、使用java8并行处理,代码很简单,响应时长很不稳定,效率也不高,不建议使用
3、使用多线程处理时,代码复杂,响应时长为单个请求中时长最长的那个,效率很高,推荐使用