1.HTTP长连接、短连接
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:Connection:keep-alive.在使用长连接的情况下,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。
2. HttpClient 连接池
HttpClient 连接池是一种复用 HTTP 连接的技术,旨在减少每次请求时建立和关闭连接的开销。通过连接池,可以显著提高 HTTP 请求的效率,尤其是在高并发场景下。
3. HTTP客户端
| 场景 | 推荐框架 | 特点 |
|---|---|---|
| 高并发、低延迟需求 | Apache HttpClient | 提供强大的连接池支持,适合复杂的 HTTP 请求逻辑 |
| 异步非阻塞请求 | Spring WebClient | 基于 Reactor 的响应式编程模型,支持异步非阻塞操作 |
| 简单的 RESTful 调用 | RestTemplate | 易于使用,但已被标记为过时(推荐迁移到 WebClient) |
| 轻量级 HTTP 客户端 | OkHttp | 支持同步和异步调用,简单易用 |
| 原生 HTTP 客户端 | Java 11 HttpClient | JDK 自带的 HTTP 客户端,支持异步和同步调用 |
| 声明式 HTTP 客户端 | Feign | 基于注解的声明式 HTTP 客户端,适合微服务间通信 |
4. RestTemplate
1.构造函数
- RestTemplate() //无参
- RestTemplate(List> messageConverters) //messageConverters转换实现类
- RestTemplate(ClientHttpRequestFactory requestFactory) //客户端连接工厂
2.ClientHttpRequestFactory实现
1.SimpleClientHttpRequestFactory
SimpleClientHttpRequestFactory(封装URLConnection)//默认的超时时间设置为-1,若出现服务器宕机的情况,该连接将永远不会被释放。
// 创建 SimpleClientHttpRequestFactory 实例
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
// 设置连接和读取超时时间(可选)
requestFactory.setConnectTimeout(10000); // 10秒连接超时
requestFactory.setReadTimeout(10000); // 10秒读取超时
2.HttpComponentsClientHttpRequestFactory
HttpComponentsClientHttpRequestFactory (封装HttpClient)
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient());
factory.setReadTimeout(10000);
factory.setConnectTimeout(10000);
3.OkHttp3ClientHttpRequestFactory
OkHttp3ClientHttpRequestFactory (封装OKHttp)
OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient());
factory.setReadTimeout(10000);
factory.setConnectTimeout(10000);
5.连接池
| 包名 | 描述 |
| org.apache.httpcomponents:httpclient | 用于 Apache HttpClient |
| com.squareup.okhttp3:okhttp | 用于 OkHttp |
| spring-boot-starter-webflux | 用于 WebClient |
| io.github.openfeign:feign-core | 用于 Feign |
1. Apache HttpClient 连接池
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
RestTemplate连接线程池,需要使用其他的 HTTP 库(默认使用的是 JDK 自己的),比如 HttpComponents、Netty、OkHttp。
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(httpRequestFactory());
}
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
@Bean
public HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
// 创建连接池管理器
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
// 设置最大连接数
connectionManager.setMaxTotal(200); // 默认值:20
// 设置每个路由的最大连接数
connectionManager.setDefaultMaxPerRoute(50); // 默认值:2
// 为特定路由设置最大连接数
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost("localhost", 8080)), 100);
//路由是对maxTotal的细分
connectionManager.setDefaultMaxPerRoute(100);
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(30000) //返回数据的超时时间
.setConnectTimeout(10000) //连接上服务器的超时时间
.setConnectionRequestTimeout(1000) //从连接池中获取连接的超时时间
.build();
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
}
}
2. OkHttp 连接池
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
return new RestTemplate(requestFactory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient());
factory.setReadTimeout(10000);
factory.setConnectTimeout(10000);
return factory;
}
@Bean
public OkHttpClient okHttpClient() {
// 设置连接池参数,最大空闲连接数200,空闲连接存活时间10s
ConnectionPool connectionPool = new ConnectionPool(200, 10, TimeUnit.SECONDS);
OkHttpClient okHttpClient = new OkHttpClient.Builder().
retryOnConnectionFailure(false)
.connectionPool(connectionPool)
.connectTimeout(3, TimeUnit.SECONDS)
.readTimeout(3, TimeUnit.SECONDS)
.writeTimeout(3, TimeUnit.SECONDS).build();
return okHttpClient;
}
}
3.Spring WebClient 连接池
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
/**
WebClient连接池
**/
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient() {
// 配置连接池
ConnectionProvider connectionProvider = ConnectionProvider.builder("webClientConnectionPool")
.maxConnections(100) // 最大连接数
.pendingAcquireTimeout(Duration.ofSeconds(30)) // 获取连接的超时时间
.maxIdleTime(Duration.ofMinutes(5)) // 空闲连接的最大存活时间
.maxLifeTime(Duration.ofMinutes(30)) // 连接的最大生命周期
.build();
// 配置HTTP客户端
HttpClient httpClient = HttpClient.create(provider)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.responseTimeout(Duration.ofSeconds(5))
.doOnConnected(conn ->
conn.addHandlerLast(new ReadTimeoutHandler(5))
.addHandlerLast(new WriteTimeoutHandler(5)));
// 构建WebClient实例
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.baseUrl("https://echo.apifox.com")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
// 添加请求日志记录功能
.filter(ExchangeFilterFunction.ofRequestProcessor(
clientRequest -> {
log.debug("Request: {} {}",
clientRequest.method(),
clientRequest.url());
return Mono.just(clientRequest);
}
))
// 添加响应日志记录功能
.filter(ExchangeFilterFunction.ofResponseProcessor(
clientResponse -> {
log.debug("Response status: {}",
clientResponse.statusCode());
return Mono.just(clientResponse);
}
))
.build();
}
}
4. Feign 连接池
引入依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
@Configuration
public class FeignHttpClientPoolConfig {
@Bean
public Client feignClient() {
// 创建连接池管理器
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// 设置最大连接数
connectionManager.setMaxTotal(200); // 默认值:20
// 设置每个路由的最大连接数
connectionManager.setDefaultMaxPerRoute(50); // 默认值:2
// 为特定路由设置最大连接数(例如 localhost:8080)
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost("localhost", 8080)), 100);
// 配置请求参数
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000) // 连接超时时间(单位:毫秒)
.setSocketTimeout(10000) // 响应超时时间(单位:毫秒)
.setConnectionRequestTimeout(2000) // 从连接池获取连接的超时时间(单位:毫秒)
.build();
// 创建 HttpClient
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.evictIdleConnections(30, TimeUnit.SECONDS) // 清理空闲连接(单位:秒)
.evictExpiredConnections() // 清理过期连接
.build();
// 返回 Feign 的 Apache HttpClient 实现
return new feign.httpclient.ApacheHttpClient(httpClient);
}
}
5.java 11 HttpClient 连接池
@Configuration
public class Java11HttpClientConfig {
@Bean
public ExecutorService executorService() {
// 创建固定大小的线程池,并设置自定义线程工厂以命名线程
ThreadFactory threadFactory = r -> {
Thread t = new Thread(r, "http-client-thread");
t.setDaemon(true); // 设置为守护线程
return t;
};
return Executors.newFixedThreadPool(10, threadFactory);
}
@Bean
public HttpClient httpClientPool(ExecutorService executorService) {
// 配置 Java 11 HttpClient
return HttpClient.newBuilder()
.executor(executorService)
.connectTimeout(java.time.Duration.ofSeconds(5)) // 连接超时时间
.version(HttpClient.Version.HTTP_2) // 使用 HTTP/2 协议
.followRedirects(HttpClient.Redirect.ALWAYS) // 自动处理重定向
.build();
}
}
本文介绍如何通过配置RestTemplate使用HTTP长连接及连接池技术提高应用性能。包括不同类型的ClientHttpRequestFactory实现方式,以及使用HttpClient和OkHttp实现连接池的具体步骤。



8511

被折叠的 条评论
为什么被折叠?



