HttpClient使用时的问题小结

在使用httpclient之前,需要导包,使用maven

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

创建一个简单的HttpClient

1.创建HttpClient实例
2.创建某种连接方法的实例
3.调用HttpClient实例的execute方法来执行请求方法
4.读取response
5.释放连接,无论执行方法是否成功

public static void main(String[] args) throws IOException {
        // 1. 创建HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 2. 创建GET请求方法实例
        HttpGet httpGet = new HttpGet("http:/baidu.com");
        // 3. 调用HttpClient实例来执行GET请求方法,得到response
        CloseableHttpResponse response = httpClient.execute(httpGet);
        // 4. 读response,判断是否访问成功
        int status = response.getStatusLine().getStatusCode();
        if (status >= 200 && status < 300) {
            // 对得到后的实例可以进行处理,例如读取回复体,读取html
            HttpEntity entity = response.getEntity();
            System.out.println(response);
            System.out.println("=======================");
            String html = EntityUtils.toString(entity);
            System.out.println(html);
        } else {
            throw new ClientProtocolException("Unexpected response status: " + status);
        }
        // 5. 释放连接
        response.close();
        httpClient.close();
    }

这样一个简单的httpclient就完成了,但是在我们正常业务代码中,可能会出现一些问题,所以我们需要进行优化改动。

频繁使用HttpClient时,会出现请求失败

频繁地开启和关闭 HttpClient 可能会导致一些性能和资源管理上的问题。下面是一些可能出现的影响:

连接泄漏:如果在频繁请求结束后没有正确地关闭 HttpClient,可能会导致连接泄漏。每次创建 HttpClient 都会创建一个连接池,如果这些连接没有被正确地关闭和释放,会占用系统资源,最终导致连接池耗尽,无法再建立新的连接。
连接池资源浪费:频繁创建和销毁 HttpClient 会导致连接池资源的浪费。每次创建 HttpClient 都需要初始化连接池、创建连接等操作,这些操作会消耗系统资源。如果频繁地创建和销毁,会增加系统开销。
性能影响:频繁创建和销毁 HttpClient 会影响性能。创建 HttpClient 需要进行一系列的初始化操作,包括连接池的初始化、DNS 解析、SSL 握手等,这些操作会耗费一定的时间。频繁地进行这些操作会增加请求的响应时间,并且可能导致系统性能下降。

为了避免以上问题,建议在应用程序的生命周期内共享一个 HttpClient 实例,而不是频繁地创建和销毁。通常情况下,HttpClient 是线程安全的,可以被多个线程共享。通过共享一个长时间存在的 HttpClient 实例,可以避免连接泄漏、减少连接池资源浪费,并且提高性能。

// 创建 HttpClient 实例
CloseableHttpClient httpClient = HttpClients.createDefault();

// 发送请求
HttpGet httpGet = new HttpGet("http://example.com");
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
    // 处理响应
} catch (IOException e) {
    // 异常处理
}

// 关闭 HttpClient,通常在应用程序关闭时执行
try {
    httpClient.close();
} catch (IOException e) {
    // 异常处理
}

通过共享一个长时间存在的 HttpClient 实例,可以避免频繁创建和销毁 HttpClient 导致的问题,提高系统的性能和资源利用率。

设置连接超时时间和读取超时时间

当我们的请求频繁并且数量特别大时,也会导致请求超时等一些其他的情况

RequestConfig requestConfig = RequestConfig.custom()
  .setConnectTimeout(5000) // 设置连接超时时间
  .setSocketTimeout(5000) // 设置读取超时时间
  .build();

HttpGet httpGet = new HttpGet("http://your-api-url");
httpGet.setConfig(requestConfig);

try (CloseableHttpClient httpClient = HttpClients.createDefault();
     CloseableHttpResponse response = httpClient.execute(httpGet)) {
    // 处理响应
} catch (IOException e) {
    // 异常处理
}

连接池配置

HttpClient 默认使用连接池管理连接,如果连接池配置不合理,可能会导致连接被频繁重用或者连接数量不足。可以通过适当调整连接池的配置来解决问题

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(200); // 设置最大连接数
cm.setDefaultMaxPerRoute(20); // 设置每个路由的最大连接数

CloseableHttpClient httpClient = HttpClients.custom()
  .setConnectionManager(cm)
  .build();

关于请求过程中内存发生泄漏问题

在使用完 HttpClient 后,确保及时释放连接。
比如CloseableHttpResponse对象和CloseableHttpClient对象,但是如果您的CloseableHttpClient 对象是通过静态加载的请注意不要关闭链接.

HttpEntity httpEntity = response.getEntity();
String responseBody = EntityUtils.toString(httpEntity)

该过程会把连接进行关闭,重新释放回httpclient连接池中

还有一种情况可以通过Entityutils.consume(httpGet)去关闭流,但需要合理的使用,如果在结果未完成之前关闭流可能会造成IO异常。

你可能感兴趣的:(java,http)