Java apache HttpClient出现奇怪的瓶颈(同步和异步)

Java apache HttpClient出现奇怪的瓶颈(同步和异步),java,performance,apache-httpclient-4.x,asynchttpclient,Java,Performance,Apache Httpclient 4.x,Asynchttpclient,我试图测试ApacheHTTP客户端库的限制,但遇到了一个奇怪的瓶颈。我的测试包括以下内容: 模拟固定80ms延迟的wiremock服务器 一种单元测试,使用org.apache.http.impl.nio.client.CloseableHttpAsyncClient在收集统计数据的同时,尽可能快地向wiremock服务器发出可配置数量的请求 一种单元测试,它使用org.apache.http.impl.client.CloseableHttpClient,在收集统计数据的同时,从可配置的

我试图测试ApacheHTTP客户端库的限制,但遇到了一个奇怪的瓶颈。我的测试包括以下内容:

  • 模拟固定80ms延迟的wiremock服务器

  • 一种单元测试,使用
    org.apache.http.impl.nio.client.CloseableHttpAsyncClient
    在收集统计数据的同时,尽可能快地向wiremock服务器发出可配置数量的请求

  • 一种单元测试,它使用
    org.apache.http.impl.client.CloseableHttpClient
    ,在收集统计数据的同时,从可配置的线程数尽可能快地向wiremock服务器发出可配置数量的请求

  • 一种单元测试,使用
    org.springframework.web.reactive.function.client.WebClient
    在收集统计数据的同时,尽可能快地向wiremock服务器发出可配置数量的请求

  • 所有的测试都显示在我的本地机器上每秒570个请求的性能相同。运行这些测试时,CPU非常低,利用率约为5%。所以我可以假设瓶颈不在CPU,而是在其他地方

    我的问题是这个瓶颈在哪里,我们如何扩大它

    我的系统配置:

    • 处理器:3.1 GHz四核Intel Core i7
    • 内存:16 GB 2133 MHz LPDDR3
    • 操作系统:OSX 10.15.5
    • Java版本:11.0.4
    我的单元测试:

    package com.blakeparmeter.com;
    导入org.apache.http.HttpResponse;
    导入org.apache.http.client.methods.CloseableHttpResponse;
    导入org.apache.http.client.methods.HttpGet;
    导入org.apache.http.concurrent.FutureCallback;
    导入org.apache.http.impl.client.CloseableHttpClient;
    导入org.apache.http.impl.client.HttpClientBuilder;
    导入org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
    导入org.apache.http.impl.nio.client.httpacyncClients;
    导入org.junit.jupiter.api.Assertions;
    导入org.junit.jupiter.api.Test;
    导入java.io.IOException;
    导入java.net.URI;
    导入java.util.concurrent.CountDownLatch;
    导入java.util.concurrent.ExecutionException;
    导入java.util.concurrent.ForkJoinPool;
    导入java.util.stream.IntStream;
    /**
    *用于说明apache HttpClient的性能瓶颈
    */
    公共级瓶颈测试{
    //测试变量
    最终整数测试=5_000;
    最终长消息间隔=1000;//毫秒
    最终URI testUri=URI.create(“http://localhost:5000/wait/fixed/empty");
    @试验
    public void testSync()引发InterruptedException、ExecutionException{
    最终int numThreads=100;
    //创建同步客户端(测试中的单元)
    最终可关闭的HttpClient unitUnderTest=HttpClientBuilder
    .create()
    .SetMaxConntTotal(5000)
    .setMaxConnPerRoute(5000)
    .build();
    //在执行器上运行测试,将结果发送到统计聚合器
    最终ForkJoinPool执行器=新的ForkJoinPool(numThreads);
    最终StatsAggregator StatsAggregator=新StatsAggregator(totalTests,messageInterval);
    executor.submit(()->IntStream.range(0,numThreads)
    .parallel()
    .forEach(threadNum->IntStream.range(0,totalTests/numThreads).forEach(testNum->{
    最终长时间运行开始=System.currentTimeMillis();
    try(final CloseableHttpResponse response=unitUnderTest.execute(new-HttpGet(testUri))){
    //我们不需要对响应执行任何操作,只需确保它已发送。
    }捕获(最终IOE例外){
    断言失败(e);
    }
    statsAggregator.addTestDuration(System.currentTimeMillis()-runStart);
    })))
    .get();
    //最后一次打印统计数据(因为我们等待执行者,所以不需要等待)
    statsAggregator.printStats();
    }
    @试验
    public void testAsync()引发InterruptedException{
    //创建异步客户端(正在测试的单元)
    最终关闭HttpAsyncClient unitUnderTest=HttpAsyncClients.custom()
    .SetMaxConntTotal(5000)
    .setMaxConnPerRoute(5000)
    .build();
    unitUnderTest.start();
    //运行所有测试,将结果发送到统计聚合器
    最终倒计时闩锁测试倒计时=新倒计时闩锁(totalTests);
    最终StatsAggregator StatsAggregator=新StatsAggregator(totalTests,messageInterval);
    IntStream.range(0,totalTests).forEach(testNum->{
    最终长时间运行开始=System.currentTimeMillis();
    execute(新的HttpGet(testUri),新的FutureCallback(){
    @凌驾
    公共无效完成(最终HttpResponse响应){
    statsAggregator.addTestDuration(System.currentTimeMillis()-runStart);
    testCountdown.countDown();
    }
    @凌驾
    公共作废失败(最终例外情况除外){
    Assertions.fail(例如getMessage());
    }
    @凌驾
    公众假期取消(){
    断言失败(“Http请求已取消”);
    }
    });
    });
    //等待执行,然后最后打印一次统计数据
    testCountdown.wait();
    statsAggregator.printStats();
    }
    @试验
    public void testReactive(){
    最终WebClient unitUnderTest=WebClient.builder().build();
    //运行所有测试,将结果发送到统计聚合器
    最终StatsAggregator StatsAggregator=新StatsAggregator(totalTests,messageInterval);
    通量范围(0,总测试)
    .flatMap(testNum->{
    最终长运行启动=系统.current