HttpComponentsClientHttpRequestFactory

发布于:2024-04-19 ⋅ 阅读:(27) ⋅ 点赞:(0)

HttpComponentsClientHttpRequestFactory

介绍

HttpComponentsClientHttpRequestFactory 是 Spring Framework 中用来封装 Apache HttpComponents HttpClient 的一个工厂类,用于创建基于 HttpClient 的 ClientHttpRequest 实例。然而,关于默认的最大连接数,这个信息通常是由底层使用的 Apache HttpClient 的配置决定的,而不是由 HttpComponentsClientHttpRequestFactory 类本身直接设定。

Apache HttpClient 默认的最大连接数(即最大并发连接数)通常取决于所使用的 HttpClient 版本以及具体的连接管理器(Connection Manager)实现。在 HttpClient 4.x 及以上版本中,最常用的连接管理器是 PoolingHttpClientConnectionManager。

对于 PoolingHttpClientConnectionManager,其默认的最大连接数取决于具体的实现版本和配置方式,但通常情况下,如果没有显式配置,其默认的最大连接数可能是以下情况之一:

  1. 200个并发连接:在某些版本或默认配置下,PoolingHttpClientConnectionManager 的默认最大连接数可能设为 200。这是 HttpClient 在没有明确限制时可能采用的一个常见值。
  2. 每个路由默认为2个并发连接:如果没有为整个连接池指定总的并发连接数,PoolingHttpClientConnectionManager 可能会根据每个路由(route)来设置默认并发连接数。每个路由通常对应一个特定的主机名加端口组合。默认情况下,每个路由可能允许最多2个并发连接。
  3. 未明确指定时的行为:随着 HttpClient 版本的更新和优化,其默认行为可能会有所变化。在一些版本中,如果没有显式配置最大连接数,实际的最大连接数可能会被设置为一个相对保守的值,或者依赖于底层操作系统对并发连接的限制。

实际

  • defaultMaxPerRouter=5
  • maxTotal=10

配置 PoolingHttpClientConnectionManager 时,可以使用如下的方法来设置最大连接数:

PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotalConnections); // 设置整个连接池的最大并发连接数
connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute); // 设置每个路由的默认最大并发连接数
// ... 其他配置项

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

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);

其中,maxTotalConnections 和 defaultMaxPerRoute 应替换为你希望设置的具体数值。这样,你就能够精确地控制HttpComponentsClientHttpRequestFactory 使用的 HttpClient 实例的最大连接数了。

defaultMaxPerRoute

defaultMaxPerRoute 是 Apache HttpClient 的 PoolingHttpClientConnectionManager 类中的一个重要参数,用于控制对同一路由(route)的最大并发连接数。在理解 defaultMaxPerRoute 的含义和作用时,我们需要先了解以下几个关键概念:

1.路由(Route)

在 HttpClient 的上下文中,路由(route)是指一个特定的网络路径,通常由以下三个要素组成:

  • Scheme(协议):例如 http 或 https。
  • Host(主机名):例如 www.example.com。
  • Port(端口号):例如 80 或 443。

一个路由可以简单理解为一个特定的服务器地址,用于标识网络请求的目标。不同的路由之间即使指向同一个主机名,但如果协议或端口号不同,也会被视为独立的路由。

2.最大并发连接数(Max Per Route)

最大并发连接数(Max Per Route),即 defaultMaxPerRoute,定义了 HttpClient 对于任何一个特定路由(如 http://www.example.com:80)允许同时打开的最大 HTTP 连接数量。这个限制有助于防止过度消耗目标服务器资源,尤其是在进行大量并发请求时。

3.defaultMaxPerRoute 的作用

  • 限制对单个主机的并发请求

    设置 defaultMaxPerRoute 可以限制对单一主机(或同一路由)的同时活跃连接数,从而避免因短时间内发起过多请求导致目标服务器过载,或者触发其反爬虫机制。这对于遵守服务提供商的使用协议,以及维持良好的网络礼仪非常重要
    
  • 平衡资源分配

    在多主机或多路由的场景下,defaultMaxPerRoute 可以帮助平衡各个路由之间的资源分配。例如,如果你的应用需要向多个不同的网站发送请求,defaultMaxPerRoute 可以确保不会因为某个网站的请求过多而占用所有可用的连接,从而影响到其他网站的请求处理。
    
  • 配合全局最大连接数

    defaultMaxPerRoute 通常与 PoolingHttpClientConnectionManager 的另一个参数 maxTotal(整个连接池的最大并发连接数)一起使用。maxTotal 设定了整个 HttpClient 实例允许的最大并发连接总数,而 defaultMaxPerRoute 则细化到每个路由。这两个参数共同约束了 HttpClient 的连接管理策略
    
  • 配置 defaultMaxPerRoute

    在创建 PoolingHttpClientConnectionManager 实例时,可以通过 setDefaultMaxPerRoute() 方法来设置 defaultMaxPerRoute 的值。例如:

PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setDefaultMaxPerRoute(5); // 设置每个路由的最大并发连接数为5

// 或者针对特定路由单独设置
HttpRoute specificRoute = new HttpRoute(new HttpHost("www.example.com", 80, "http"));
connectionManager.setMaxPerRoute(specificRoute, 10); // 为特定路由设置最大并发连接数为10

// 其他配置...

在这个例子中,我们设置了默认情况下每个路由的最大并发连接数为 5。这意味着,对于任何未经特殊配置的路由(如 http://www.example.com:80),同时最多只能有 5 个活跃的 HTTP 连接。如果需要为特定路由单独设置最大并发连接数,可以使用 setMaxPerRoute() 方法,如示例中的 specificRoute。

总结来说,defaultMaxPerRoute 是 Apache HttpClient 中 PoolingHttpClientConnectionManager 的一个关键配置项,用于控制对每个路由的最大并发连接数,旨在保护目标服务器资源、平衡请求分布,并与全局最大连接数配合,共同实现高效的连接管理。在实际使用 HttpClient 时,应根据应用需求和目标服务器的承受能力,合理设置 defaultMaxPerRoute 和 maxTotal 参数。

示例

以下是一个使用 Spring 的 RestTemplate 配合 HttpComponentsClientHttpRequestFactory 的使用案例。在这个例子中,我们将创建一个 RestTemplate 实例,将其配置为使用 HttpComponentsClientHttpRequestFactory,并设置 PoolingHttpClientConnectionManager 来控制并发连接数。然后,我们将使用这个配置好的 RestTemplate 发起一个简单的 GET 请求。

import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

public class RestTemplateExample {

    public static void main(String[] args) {
        // 创建并配置PoolingHttpClientConnectionManager
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(100); // 设置整个连接池的最大并发连接数
        connectionManager.setDefaultMaxPerRoute(20); // 设置每个路由的最大并发连接数

        // 创建并配置CloseableHttpClient
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(3000) // 设置连接超时时间(毫秒)
                .setSocketTimeout(5000) // 设置读取超时时间(毫秒)
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();

        // 创建HttpComponentsClientHttpRequestFactory并设置HttpClient实例
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);

        // 创建并配置RestTemplate
        RestTemplate restTemplate = new RestTemplate(requestFactory);

        // 使用RestTemplate发起GET请求
        String url = "https://api.example.com/data";
        String response = restTemplate.getForObject(url, String.class);

        System.out.println("Response: " + response);
    }
}

在这个案例中:

  1. 我们首先创建了一个 PoolingHttpClientConnectionManager 实例,并设置了全局最大并发连接数(maxTotal)为 100,每个路由的最大并发连接数(defaultMaxPerRoute)为 20。
  2. 接下来,我们创建了一个 CloseableHttpClient 实例,为其配置了 PoolingHttpClientConnectionManager,并设置了请求的连接超时时间和读取超时时间。这些配置可以根据实际需求进行调整。
  3. 然后,我们创建了一个 HttpComponentsClientHttpRequestFactory 实例,并将之前配置好的 CloseableHttpClient 实例传递给它。这样,RestTemplate 将使用这个工厂来创建基于 HttpComponents 的 ClientHttpRequest 实例。
  4. 使用构造函数 new RestTemplate(requestFactory) 创建了一个 RestTemplate 实例,将其与已配置好的 HttpComponentsClientHttpRequestFactory 关联起来。
  5. 最后,我们使用 RestTemplate 发起了一个 GET 请求,请求的 URL 为 “https://api.example.com/data”,期望响应类型为 String。请求的结果存储在变量 response 中,并打印出来。

通过这样的配置,我们成功地将 RestTemplate 与 HttpComponentsClientHttpRequestFactory 结合起来,利用 HttpComponents 的强大功能(如连接池管理、超时控制等)来提升 HTTP 请求的性能和可靠性。你可以根据实际项目的需求,进一步调整 PoolingHttpClientConnectionManager、RequestConfig 和 RestTemplate 的相关配置。

RestTemplate的负载均衡策略是什么,怎么修改他的负载均衡策略

  • RestTemplate 本身并不直接支持负载均衡功能。它是一个简单的 HTTP 客户端工具,用于发送 HTTP 请求到指定的 URL,并接收响应。当您使用 RestTemplate 访问一个服务时,您通常会提供服务的完整 URL,这意味着每次请求都会直接定位到该 URL 指定的服务实例。
  • 如果您想要实现负载均衡,通常需要结合其他组件或框架,如 Spring Cloud Netflix 的 Ribbon 或 Spring Cloud Load Balancer。这些组件可以在 RestTemplate 之上提供客户端负载均衡能力,根据一定的策略从服务注册中心(如 Eureka)中选择一个可用的服务实例来转发请求。

以下是使用 Ribbon 或 Spring Cloud Load Balancer 修改 RestTemplate 负载均衡策略的说明:

使用 Spring Cloud Netflix Ribbon

1.添加依赖

确保您的项目已经包含了 Spring Cloud Netflix 的 spring-cloud-starter-netflix-ribbon 依赖。

2.配置 Ribbon

ribbon:
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule # 使用轮询策略

3.使用 RestTemplate 与 Ribbon 结合

在代码中,您可以通过注入 @LoadBalanced 注解的 RestTemplate 来启用客户端负载均衡:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class Application {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
// 在其他类中使用
@Service
public class SomeService {

    private final RestTemplate restTemplate;

    @Autowired
    public SomeService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String callService(String serviceName) {
        return restTemplate.getForObject("http://" + serviceName + "/endpoint", String.class);
    }
}

在上述代码中,RestTemplate 通过 @LoadBalanced 注解获得了客户端负载均衡能力。当调用 restTemplate.getForObject() 方法时,它会根据服务名(如 serviceName)从服务注册中心(如 Eureka)选择一个可用的服务实例进行请求。

4.更改负载均衡策略

要更改负载均衡策略,您可以自定义一个实现 com.netflix.loadbalancer.IRule 接口的类,并在配置文件中指定该类的全限定名作为 NFLoadBalancerRuleClassName 的值。例如,如果您实现了名为 MyCustomRule 的自定义策略,配置如下:

ribbon:
  NFLoadBalancerRuleClassName: com.example.MyCustomRule

使用 Spring Cloud Load Balancer

1.添加依赖

确保您的项目已经包含了 Spring Cloud Load Balancer 的 spring-cloud-starter-loadbalancer 依赖。

2.配置负载均衡器

在 Spring Boot 应用的配置文件中,可以配置 Spring Cloud Load Balancer 的相关属性,包括负载均衡策略。例如:

spring:
  cloud:
    loadbalancer:
      ribbon:
        enabled: false # 关闭Ribbon以使用Spring Cloud Load Balancer
      # 自定义负载均衡器
      # loadbalancer:
      #   default-lb-algorithm-class-name: com.example.MyCustomLoadBalancer

      # 针对特定服务的负载均衡器配置
      # service-id:
      #   lb-algorithm-type: ROUND_ROBIN # 使用轮询策略

3.使用 RestTemplate 与 Spring Cloud Load Balancer 结合

与使用 Ribbon 类似,您可以通过注入 @LoadBalanced 注解的 RestTemplate 来启用客户端负载均衡

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class Application {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
// 在其他类中使用
@Service
public class SomeService {

    private final RestTemplate restTemplate;

    @Autowired
    public SomeService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String callService(String serviceName) {
        return restTemplate.getForObject("http://" + serviceName + "/endpoint", String.class);
    }
}

4.更改负载均衡策略

Spring Cloud Load Balancer 提供了多种内置的负载均衡策略,可以通过配置 spring.cloud.loadbalancer.default-lb-algorithm-type 或 spring.cloud.loadbalancer.service-id.lb-algorithm-type 来选择。支持的策略包括但不限于:

  • ROUND_ROBIN:轮询
  • RANDOM:随机
  • WEIGHTED_RESPONSE_TIME:响应时间加权
  • LEAST_REQUEST:最少请求数

要使用自定义负载均衡策略,您需要实现 org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer 或 org.springframework.cloud.loadbalancer.core.BlockingLoadBalancer 接口,并在配置中指定该类的全限定名。具体实现和配置方法请参考 Spring Cloud Load Balancer 的官方文档。

综上所述,RestTemplate 本身不具备负载均衡能力,需要结合 Ribbon 或 Spring Cloud Load Balancer 才能实现。通过配置相应的负载均衡策略,您可以控制服务实例的选择逻辑。如果您需要自定义策略,可以按照上述步骤实现