httpclient连接池的测试报告(jmeter做并发测试工具)

本文对比测试了在高并发场景下,使用与未使用HTTP连接池的HttpClient性能表现。结果显示,使用连接池能显著提高并发数,降低错误率,从而大幅提升系统性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        下午,经理找我说Php的curl的在高峰期经常出现连接超时的情况,Java会不会呢,让用httpclient来做一下测试。我就作了两个对比测试。一个是httpclient没用连接池,一个有用连接池。使用spring boot做web服务,选择百度、bing用jmeter web请求测试。为什么选择这两个,因为这两个不容易报错,其他搜索引擎多请求几次就报错了。

spirng boot web的控制器代码如下 

import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Random;

@RestController
public class IndexController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private static String URLARRAY[] = {"https://www.baidu.com/s?wd=%s", "https://cn.bing.com/search?q=%s"};

    @RequestMapping("/")
    public String index(@RequestParam(value = "name", defaultValue = "helloworld") String name) throws IOException {
        int i = new Random().nextInt(URLARRAY.length);
        String url = URLARRAY[i];
        url = String.format(url, name);
        logger.debug("调用URL是{}", url);
        try {
            String value = HttpClientUtils.get(url);
        } catch (Exception ex) {
            logger.error("出错了", ex);
            throw ex;
        }
        return "成功了" + url;
    }
}

这个核心调用的是HttpClientUtils.get(url)来请求web。

首先贴上没有使用连接池的的httpClinetUtils代码

public class HttpClientUtils {

    private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
    private static RequestConfig REQUESTCONFIG = RequestConfig.custom()
            .setSocketTimeout(1000)
            .setConnectTimeout(1000)
            .setConnectionRequestTimeout(1000)
            .build();

    public static String get(String url) throws IOException {
        CloseableHttpClient httpclient = HttpClientBuilder.create().setRetryHandler((exception, executionCount, context) -> {
            return false;
        }).setDefaultRequestConfig(REQUESTCONFIG).build();
        try {

            HttpGet httpget = new HttpGet(url);
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                @Override
                public String handleResponse(
                        final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        logger.error("请求{},出现了错误{}", url, status);
                        return "出错了";
                        //throw new ClientProtocolException("Unexpected response status: " + status);
                    }
                }

            };
            String responseBody = httpclient.execute(httpget, responseHandler);
            return responseBody;
        } finally {
            httpclient.close();
        }
    }
}

可以看到没用连接池情况下,httpclient不能重复使用,使用完要及时关闭

Jmete50个线程下测试结果 

可以看到并发数才90,而且出错率达到了11%

使用连接池的httpClinetUtils代码

package com.example.testhttpclient.utils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Map;

public class HttpClientUtils {
    private static CloseableHttpClient HTTPCLIENT;
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
    private static RequestConfig REQUESTCONFIG = RequestConfig.custom()
            .setSocketTimeout(1000)
            .setConnectTimeout(1000)
            .setConnectionRequestTimeout(1000)
            .build();
    static PoolingHttpClientConnectionManager cm;

    static {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

        HTTPCLIENT = HttpClientBuilder.create().setRetryHandler((exception, executionCount, context) -> {
            return false;
        }).setDefaultRequestConfig(REQUESTCONFIG).setConnectionManager(cm).build();

    }


    public static String get(String url) throws IOException {
        try {

            HttpGet httpget = new HttpGet(url);
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                @Override
                public String handleResponse(
                        final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        logger.error("请求{},出现了错误{}", url, status);
                        return "出错了";
                        //throw new ClientProtocolException("Unexpected response status: " + status);
                    }
                }

            };
            String responseBody = HTTPCLIENT.execute(httpget, responseHandler);
            return responseBody;
        } finally {
            
        }
    }
}

jmeter50个线程测试结果

可以看到并发数达到了500,错误率也降到了0.19%,性能提高了5倍不止。

结论:

      所以在高并发情况下,使用是http连接池很重要,不然并发数最高才90,而且还容易超时

下面是jmeter的脚本文件,供参考

链接: https://pan.baidu.com/s/144wbx3LGowHLkPcvsMRUZg 提取码: jhnc 复制这段内容后打开百度网盘手机App,操作更方便哦

<think>嗯,用户想了解如何配置JMeter来执行1万并发的性能测试。首先,我需要回忆一下JMeter的相关知识,确保信息准确。用户提到的并发数很高,达到1万,这可能涉及到分布式测试和资源优化的问题。 首先,JMeter本身单机的并发能力受限于硬件资源,比如CPU、内存和网络。所以,单机可能无法支撑1万并发,这时候需要考虑使用分布式测试,也就是多台机器同时运行JMeter来分担负载。需要提醒用户设置主控机和多个执行机,并确保它们之间的网络连接畅通,时间同步,而且防火墙设置正确。 然后,关于JMeter的配置,线程组的设置是关键。用户需要设置线程数、Ramp-Up时间和循环次数。对于1万并发,可能需要将线程数分成多个执行机来处理,比如每个执行机跑2500线程,总共4台。Ramp-Up时间要合理,避免瞬间启动太多线程导致服务器崩溃。可能需要逐步增加负载,比如设置较长的Ramp-Up时间,让线程逐渐启动。 接下来,HTTP请求的配置也很重要。用户需要确保正确配置协议、服务器地址、端口、路径和方法。对于高并发,可能需要使用连接池,调整超时设置,以及启用Keep-Alive来复用连接,减少建立连接的开销。 监听器的选择也很关键,高并发下如果使用太多监听器会消耗大量内存,导致OOM错误。应该建议使用简单数据写入文件,或者使用后端监听器,比如InfluxDB和Grafana组合来实时监控,这样不会占用太多资源。 参数化和数据池是另一个方面。为了模拟真实用户,需要不同的数据,比如用户登录信息。使用CSV文件读取数据,确保每个线程使用不同的数据,避免缓存影响测试结果。还要注意CSV文件的路径和配置是否正确。 断言和定时器可以增加测试的真实性。添加响应断言来验证请求是否成功,使用随机定时器模拟用户思考时间,避免所有请求同时发送,给服务器造成不真实的压力。 资源监控部分,JMeter本身可能不够,需要额外的工具,比如服务器监控工具(如Grafana+Prometheus)来跟踪CPU、内存、网络等指标。同时,JMeter的PerfMon插件可以监控服务器资源使用情况,帮助定位瓶颈。 分布式测试的具体步骤包括安装JMeter在所有机器上,配置主控机修改jmeter.properties中的remote_hosts,启动执行机的agent,然后运行测试。需要注意的是,执行机的数量要足够,网络带宽也要足够,否则可能成为瓶颈。 性能优化方面,建议使用命令行模式运行测试,节省GUI的开销。调整JVM参数,增加堆内存,避免GC问题。关闭不必要的监听器和日志,减少资源消耗。 结果分析阶段,生成聚合报告,关注平均响应时间、错误率和吞吐量。如果错误率高,需要检查服务器日志,确定是应用瓶颈还是资源不足。使用图形结果或HTML报告来可视化数据,更容易发现问题。 最后,根据引用内容,用户提到的引用[3]是关于JMeter实践的基本流程,比如抓取URL,设置线程组等。引用[2]提到其他工具可能更适合高灵活度测试,但JMeter在资源监控和报表方面可能需要补充工具。引用[1]强调明确测试目标和模拟真实场景,这在配置JMeter时需要特别注意,比如参数化和定时器的使用。 可能用户没有明确说出来的需求是,他们可能在实际操作中遇到了性能问题,或者需要确保测试结果可靠。需要提醒他们逐步增加并发,先小规模测试,再逐步放大,避免直接1万并发导致系统崩溃。同时,测试环境和生产环境要尽可能一致,才能得到有意义的结果。 总结下来,步骤应该是:分布式环境搭建、JMeter配置优化、参数化数据、资源监控、结果分析,以及遵循性能测试的最佳实践,比如逐步加压和真实场景模拟。</think>### JMeter配置万级并发性能测试分步指南 #### 一、硬件与分布式架构 1. **单机限制突破**:单台JMeter最高支持约3000线程(与硬件配置相关),需采用分布式架构。推荐配置1台主控机 + 4台执行机(每台2500线程)[^3] 2. **网络要求**:主控机与执行机需保持千兆网络连接,建议部署在同一局域网内 3. **硬件规格建议**: - 执行机:16核CPU/32GB内存/SSD硬盘 - 主控机:8核CPU/16GB内存(主要用于协调测试) #### 二、核心配置步骤 1. **线程组设置**: ```java Number of Threads: 10000 Ramp-Up Period: 600 // 建议10分钟内逐步加压 Loop Count: Forever // 配合持续时间使用 ``` 2. **HTTP请求默认值**: ```xml <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP请求默认值"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"/> <stringProp name="HTTPSampler.domain">api.yourdomain.com</stringProp> <stringProp name="HTTPSampler.port">443</stringProp> <stringProp name="HTTPSampler.protocol">https</stringProp> </ConfigTestElement> ``` 3. **连接池优化**: ```properties httpclient4.time_to_live=60000 // 连接存活时间 httpclient4.max_total=2000 // 每执行机最大连接数 ``` #### 三、关键优化策略 1. **JVM参数调整**(jmeter.sh): ```shell HEAP="-Xms24g -Xmx24g -XX:MaxMetaspaceSize=512m" ``` 2. **禁用非必要组件**: - 移除View Results Tree监听器 - 使用简单数据写入器替代图形报表 3. **参数化实现**(CSV配置示例): ```csv userId,userToken test001,a1b2c3d4 test002,e5f6g7h8 ... ``` #### 四、监控体系搭建 1. **服务器监控矩阵**: | 指标 | 工具 | 告警阈值 | |-------------|-------------------|----------| | CPU使用率 | Prometheus+NodeExporter | >85% | | 内存占用 | JMeter PerfMon | >90% | | 网络吞吐量 | iftop | 带宽80% | 2. **JMeter监控配置**: ```xml <kg.apc.jmeter.jmxmon.JMXMonCollector guiclass="kg.apc.jmeter.jmxmon.JMXMonCollectorGui" testclass="kg.apc.jmeter.jmxmon.JMXMonCollector" testname="PerfMon Metrics Collector"> <collectionProp name="metrics_settings"> <collectionProp name=""> <stringProp name="host">192.168.1.10</stringProp> <stringProp name="port">1234</stringProp> <stringProp name="metric">cpu</stringProp> </collectionProp> </collectionProp> </kg.apc.jmeter.jmxmon.JMXMonCollector> ``` #### 五、执行策略优化 1. **梯度加压方案**: ```python # 梯度加压脚本示例 phases = [ {'duration': 300, 'users': 1000}, # 5分钟加载1000用户 {'duration': 600, 'users': 4000}, # 10分钟加载至5000 {'duration': 900, 'users': 10000} # 15分钟达到目标并发 ] ``` 2. **异常处理机制**: ```java if (prev.isSuccessful()) { SampleResult.setIgnore(); // 成功请求不记录详细数据 } else { SampleResult.setDataEncoding("UTF-8"); SampleResult.setResponseData(prev.getResponseData()); } ``` #### 六、结果分析要点 1. **关键性能指标**: $$ TPS = \frac{Total\ Transactions}{Test\ Duration} $$ $$ Error\ Rate = \frac{Failed\ Requests}{Total\ Requests} \times 100\% $$ 2. **瓶颈定位流程**: ```mermaid graph TD A[响应时间超标] --> B{错误类型} B -->|5xx| C[应用服务器瓶颈] B -->|4xx| D[参数配置问题] B -->|Timeout| E[网络/中间件瓶颈] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值