admin管理员组

文章数量:1031761

【连载 29】HttpClient详解之客户端

在当今高性能、高并发的网络应用开发中,HTTP客户端作为系统间通信的核心组件,其配置优化直接影响着整体性能表现。Apache HttpClient作为Java生态中最成熟、功能最丰富的HTTP客户端工具库,为开发者提供了高度可定制的连接管理、请求控制和异常处理机制。本节将深入剖析HttpClient的核心配置项,从连接池管理、SSL安全策略到超时控制、重试机制,全面讲解如何构建一个高性能、高可靠的HTTP客户端实例。通过精细调节连接数、路由策略、报文约束等参数,开发者能够有效提升系统吞吐量,避免资源浪费,同时掌握多用户并发场景下的Cookie管理技巧和异常请求的智能重试策略,为构建企业级应用通信框架奠定坚实基础。

4.1节我们学习了HTTP协议的基础知识以及对应的Java HttpClient中的类,下面讲解HttpClient中这些类和对象的详细使用语法和常见功能的代码实现。本节的代码内容均包含在org.funtester.performance.books.chapter04.section2包中。

4.2.1 请求客户端

在上文中我用到了org.apache.http.impl.client.HttpClients#createDefault创建了一个默认的CloseableHttpClient的请求客户端。但实际上CloseableHttpClient类的设置细节非常多,对于实际的性能测试影响也不尽相同。下面我们来逐一介绍几个重量级的设置项。

1. HttpClientConnectionManager

HTTP请求客户端最重要的是连接管理器org.apache.http.conn.HttpClientConnectionManager,在性能测试场景下,我们选择连接池管理器PoolingHttpClientConnectionManager作为该接口的实现类。有关于池化这个概念,在性能测试中会经常遇到,我在后面章节会详细讲解。

要创建连接池管理器,首先要创建一个连接工厂(ConnectionSocketFactory)的注册表(Registry),用于处理 HTTP 和 HTTPS 连接。代码如下:

代码语言:javascript代码运行次数:0运行复制
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() // 创建套接字注册器  
        .register("http", PlainConnectionSocketFactory.INSTANCE) // 注册http套接字工厂  
        .register("https", new SSLConnectionSocketFactory(createIgnoreVerifySSL(), NoopHostnameVerifier.INSTANCE)) // 注册https套接字工厂  
        .build(); // 创建套接字注册器  

其中两次调用了register()方法分别创建了httphttps套接字连接工厂,用于创建非加密和加密的HTTP连接。在注册https套接字工厂类时用到了createIgnoreVerifySSL()方法来创建自定义的SSL配置,并且使用NoopHostnameVerifier.INSTANCE当作主机验证对象,创建了SSLConnectionSocketFactory对象。该方法不进行主机名验证,有一定的安全风险,通常在测试或不需要主机名验证的情况使用。在实际应用中,处理 SSL/TLS 连接时需要谨慎并正确验证证书,确保连接的安全性。

createIgnoreVerifySSL()方法内容如下:

代码语言:javascript代码运行次数:0运行复制
/**  
 * 获取SSL套接字对象 重点重点:设置tls协议的版本  
 * @return  
 */  
private static SSLContext createIgnoreVerifySSL() {  
    SSLContext sslContext = null; // 创建套接字对象  
    try {  
        sslContext = SSLContext.getInstance(SSL_VERSION); // 指定TLS版本  
    } catch (NoSuchAlgorithmException e) {  
        e.printStackTrace();  
    }  
    // 实现X509TrustManager接口,用于绕过验证  
    X509TrustManager trustManager = new X509TrustManager() {  
        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) {}  
        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) {}  
        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
            returnnull;  
        }  
    };  
    try {  
        sslContext.init(null, new TrustManager[]{trustManager}, null); // 初始化sslContext对象  
    } catch (KeyManagementException e) {  
        e.printStackTrace();  
    }  
    return sslContext;  
}  

下面创建一个PoolingHttpClientConnectionManager对象,并且对其中重要参数进行配置,代码如下:

代码语言:javascript代码运行次数:0运行复制
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, getDnsResolver()); // 创建连接池管理器  
MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(MAX_HEADER_COUNT).setMaxLineLength(MAX_LINE_LENGTH).build();  
ConnectionConfig connectionConfig = ConnectionConfig.custom()  
        .setMalformedInputAction(CodingErrorAction.IGNORE)  
        .setUnmappableInputAction(CodingErrorAction.IGNORE)  
        .setCharset(DEFAULT_CHARSET)  
        .setMessageConstraints(messageConstraints)  
        .build(); // 创建连接配置  
connManager.setDefaultConnectionConfig(connectionConfig); // 设置默认连接配置  
connManager.setMaxTotal(MAX_TOTAL_CONNECTION); // 设置最大连接数  
connManager.setDefaultMaxPerRoute(MAX_PER_ROUTE_CONNECTION); // 设置每个路由最大连接数  

第一行构造方法中,用到了第二个参数DnsResolver,本地自定义DNS解析器,通常用来将主机名/域名解析到对应的IP地址上。在HttpClient中,自定义的DNS解析器可以在特定主机名/域名进行解析时,按照自定义的逻辑进行。通常用于进行DNS解析结果的保存,减少查询DNS查询次数,提升程序整体性能,另外还可以用来实现本地负载均衡策略和对特定域名的解析。 其他代码均为配置功能,其中一类是连接数量的配比限制,另外一类则是单个连接的属性设置。唯一例外的就是默认字符集的配置。在实际性能测试当中,这些配置的值均需要根据实际情况而定,而且不会频繁改动,可以使用配置文件或者写到常量类中。下面是常量的默认配置以及含义:

代码语言:javascript代码运行次数:0运行复制
/**  
 * 默认字符集,用于请求体和响应体的解析  
 */  
publicstatic Charset DEFAULT_CHARSET = Charset.forName("UTF-8");  

/**  
 * 最大连接数,连接池最大连接数,单位个  
 */
publicstaticint MAX_TOTAL_CONNECTION = 8000;  

/**  
 * 每个路由最大连接数,路由是对maxTotal的细分,例如:一个域名对应一个路由,一个ip对应一个路由  
 */
publicstaticint MAX_PER_ROUTE_CONNECTION = 1000;  

/**  
 * 最大请求头数量,单位个  
 */
publicstaticint MAX_HEADER_COUNT = 100;  

/**  
 * 最大请求行长度,单位字符  
 */
publicstaticint MAX_LINE_LENGTH = 10000;  

/**  
 * SSL版本,默认TLSv1.2  
 */
publicstatic String SSL_VERSION = "TLSv1.2";  
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-04-05,如有侵权请联系 cloudcommunity@tencent 删除连接配置httpclient对象客户端

【连载 29】HttpClient详解之客户端

在当今高性能、高并发的网络应用开发中,HTTP客户端作为系统间通信的核心组件,其配置优化直接影响着整体性能表现。Apache HttpClient作为Java生态中最成熟、功能最丰富的HTTP客户端工具库,为开发者提供了高度可定制的连接管理、请求控制和异常处理机制。本节将深入剖析HttpClient的核心配置项,从连接池管理、SSL安全策略到超时控制、重试机制,全面讲解如何构建一个高性能、高可靠的HTTP客户端实例。通过精细调节连接数、路由策略、报文约束等参数,开发者能够有效提升系统吞吐量,避免资源浪费,同时掌握多用户并发场景下的Cookie管理技巧和异常请求的智能重试策略,为构建企业级应用通信框架奠定坚实基础。

4.1节我们学习了HTTP协议的基础知识以及对应的Java HttpClient中的类,下面讲解HttpClient中这些类和对象的详细使用语法和常见功能的代码实现。本节的代码内容均包含在org.funtester.performance.books.chapter04.section2包中。

4.2.1 请求客户端

在上文中我用到了org.apache.http.impl.client.HttpClients#createDefault创建了一个默认的CloseableHttpClient的请求客户端。但实际上CloseableHttpClient类的设置细节非常多,对于实际的性能测试影响也不尽相同。下面我们来逐一介绍几个重量级的设置项。

1. HttpClientConnectionManager

HTTP请求客户端最重要的是连接管理器org.apache.http.conn.HttpClientConnectionManager,在性能测试场景下,我们选择连接池管理器PoolingHttpClientConnectionManager作为该接口的实现类。有关于池化这个概念,在性能测试中会经常遇到,我在后面章节会详细讲解。

要创建连接池管理器,首先要创建一个连接工厂(ConnectionSocketFactory)的注册表(Registry),用于处理 HTTP 和 HTTPS 连接。代码如下:

代码语言:javascript代码运行次数:0运行复制
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() // 创建套接字注册器  
        .register("http", PlainConnectionSocketFactory.INSTANCE) // 注册http套接字工厂  
        .register("https", new SSLConnectionSocketFactory(createIgnoreVerifySSL(), NoopHostnameVerifier.INSTANCE)) // 注册https套接字工厂  
        .build(); // 创建套接字注册器  

其中两次调用了register()方法分别创建了httphttps套接字连接工厂,用于创建非加密和加密的HTTP连接。在注册https套接字工厂类时用到了createIgnoreVerifySSL()方法来创建自定义的SSL配置,并且使用NoopHostnameVerifier.INSTANCE当作主机验证对象,创建了SSLConnectionSocketFactory对象。该方法不进行主机名验证,有一定的安全风险,通常在测试或不需要主机名验证的情况使用。在实际应用中,处理 SSL/TLS 连接时需要谨慎并正确验证证书,确保连接的安全性。

createIgnoreVerifySSL()方法内容如下:

代码语言:javascript代码运行次数:0运行复制
/**  
 * 获取SSL套接字对象 重点重点:设置tls协议的版本  
 * @return  
 */  
private static SSLContext createIgnoreVerifySSL() {  
    SSLContext sslContext = null; // 创建套接字对象  
    try {  
        sslContext = SSLContext.getInstance(SSL_VERSION); // 指定TLS版本  
    } catch (NoSuchAlgorithmException e) {  
        e.printStackTrace();  
    }  
    // 实现X509TrustManager接口,用于绕过验证  
    X509TrustManager trustManager = new X509TrustManager() {  
        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) {}  
        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) {}  
        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
            returnnull;  
        }  
    };  
    try {  
        sslContext.init(null, new TrustManager[]{trustManager}, null); // 初始化sslContext对象  
    } catch (KeyManagementException e) {  
        e.printStackTrace();  
    }  
    return sslContext;  
}  

下面创建一个PoolingHttpClientConnectionManager对象,并且对其中重要参数进行配置,代码如下:

代码语言:javascript代码运行次数:0运行复制
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, getDnsResolver()); // 创建连接池管理器  
MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(MAX_HEADER_COUNT).setMaxLineLength(MAX_LINE_LENGTH).build();  
ConnectionConfig connectionConfig = ConnectionConfig.custom()  
        .setMalformedInputAction(CodingErrorAction.IGNORE)  
        .setUnmappableInputAction(CodingErrorAction.IGNORE)  
        .setCharset(DEFAULT_CHARSET)  
        .setMessageConstraints(messageConstraints)  
        .build(); // 创建连接配置  
connManager.setDefaultConnectionConfig(connectionConfig); // 设置默认连接配置  
connManager.setMaxTotal(MAX_TOTAL_CONNECTION); // 设置最大连接数  
connManager.setDefaultMaxPerRoute(MAX_PER_ROUTE_CONNECTION); // 设置每个路由最大连接数  

第一行构造方法中,用到了第二个参数DnsResolver,本地自定义DNS解析器,通常用来将主机名/域名解析到对应的IP地址上。在HttpClient中,自定义的DNS解析器可以在特定主机名/域名进行解析时,按照自定义的逻辑进行。通常用于进行DNS解析结果的保存,减少查询DNS查询次数,提升程序整体性能,另外还可以用来实现本地负载均衡策略和对特定域名的解析。 其他代码均为配置功能,其中一类是连接数量的配比限制,另外一类则是单个连接的属性设置。唯一例外的就是默认字符集的配置。在实际性能测试当中,这些配置的值均需要根据实际情况而定,而且不会频繁改动,可以使用配置文件或者写到常量类中。下面是常量的默认配置以及含义:

代码语言:javascript代码运行次数:0运行复制
/**  
 * 默认字符集,用于请求体和响应体的解析  
 */  
publicstatic Charset DEFAULT_CHARSET = Charset.forName("UTF-8");  

/**  
 * 最大连接数,连接池最大连接数,单位个  
 */
publicstaticint MAX_TOTAL_CONNECTION = 8000;  

/**  
 * 每个路由最大连接数,路由是对maxTotal的细分,例如:一个域名对应一个路由,一个ip对应一个路由  
 */
publicstaticint MAX_PER_ROUTE_CONNECTION = 1000;  

/**  
 * 最大请求头数量,单位个  
 */
publicstaticint MAX_HEADER_COUNT = 100;  

/**  
 * 最大请求行长度,单位字符  
 */
publicstaticint MAX_LINE_LENGTH = 10000;  

/**  
 * SSL版本,默认TLSv1.2  
 */
publicstatic String SSL_VERSION = "TLSv1.2";  
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-04-05,如有侵权请联系 cloudcommunity@tencent 删除连接配置httpclient对象客户端

本文标签: 连载 29HttpClient详解之客户端