总 所周知http1.1(http1.0不是标准,依服务器而定)是支持长连接的,长连接能够保证服务器和客户端的socket能够高效利用,减少握手等额 外的开销。httpClient在正常情况下会带上Connection: keep-alive表示我是支持长连接的,当完成一个请求后,视情况决定是否关闭连接。
正常情况下,服务器在返回内容的头中会带上如下信息:
但是如果服务器端连接次数计数达到指定值时,则会在返回内容中添加Connection: close信息,表示该连接将被关闭。
这 个时候该connection就失效了,客户端如果下次请求服务器的话,需要重新创建一个新的连接。但是有个问题,是否连接保持是由服务器端决定的,一旦 连接超时导致connection close,服务器是不会专门通知客户端的,所以我们不能依赖Connection: close信息来决定是否关闭socket。我们先来看看tomcat对长连接的配置。下面是一个典型的配置长连接的方式:
其中:
keepAliveTimeout:表示在下次请求过来之前,tomcat保持该连接多久。这就是说假如客户端不断有请求过来,且为超过过期时间,则该连接将一直保持。
maxKeepAliveRequests:表示该连接最大支持的请求数。超过该请求数的连接也将被关闭(此时就会返回一个Connection: close头给客户端)。
由 于keeplive的不确定性,这对客户端高效的实现http请求带来了一定挑战。在httpClient中对连接的复用采用了多种机制同时保证,但是这 需要和服务器端一起配合。如果服务器端和客户端在keepAlive相关的配置不匹配的话,轻则效率低下,重则伤筋动骨,具体有哪些需要注意的地方?下面 一一道来。
http连接池
httpClient提供了连接池实现连接的复用,这是实现高效请求的基础,下面是给httpClient设置连接池的方法:
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); //连接池最大生成连接数200 cm.setMaxTotal(200); // 默认设置route最大连接数为20 cm.setDefaultMaxPerRoute(20); // 指定专门的route,设置最大连接数为80 HttpHost localhost = new HttpHost("locahost", 80); cm.setMaxPerRoute(new HttpRoute(localhost), 50); // 创建httpClient CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(cm) .build();
有几个需要注意的地方:
1.如果你的客户端连接的目标服务器只有一个,那么大可设置最大route连接数和最大连接池连接数相同,以便高效利用连接池中创建的连接。
2.创建的httpClient对象是线程安全的,如果连接的目标服务器只有一个的话,创建一个全局对象即可。一个对象好比开了一个浏览器,多个线程无需每次请求时专门开一个浏览器,统一一个即可。
3.如果httpClient对象不再使用,记得关闭,释放与服务器保持连接的socket,以便服务器更高效的释放资源。
连接清理线程
虽 然连接池有了,但是由于http连接的特殊性(只有在通讯正在进行(block)时才能够对IO事件做出反应)。一旦连接被放回连接池后,我们无从知道该 连接是否还是keepalive的,且此时也无法监控当前socket的状态(即服务器主动关闭了连接,但客户端没有通讯时是不知道当前连接的状态是怎样 的)。怎么办呢?httpClient采用了一个折中的方案来检查连接的“状态”,就是由客户端自己通过配置去主动关闭其认为是失效的连接。具体方法如 下:
public static class IdleConnectionMonitorThread extends Thread { private final HttpClientConnectionManager connMgr; private volatile boolean shutdown; public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) { super(); this.connMgr = connMgr; } @Override public void run() { try { while (!shutdown) { synchronized (this) { wait(5000); // Close expired connections connMgr.closeExpiredConnections(); // Optionally, close connections // that have been idle longer than 30 sec connMgr.closeIdleConnections(30, TimeUnit.SECONDS); } } } catch (InterruptedException ex) { // terminate } } public void shutdown() { shutdown = true; synchronized (this) { notifyAll(); } } }
我 们新建了一个Thread,该Thread每隔5s进行一次清理,把认为是expired或空闲超过30s的连接给关闭掉。这里关闭空闲的连接好理解。问 题是关闭expired的连接,什么样的连接才算是expired呢?刚才说过客户端是无法检测到对应的连接是否是alive的,故通过一个配置告诉 httpClient每个连接大概什么时候会断掉,httpClient会认为过了该时间的连接就是expired的连接。默认情况 下,httpClient认为只要连接上服务器的socket将永远不会断掉。显然这种假设过于乐观。
keepalive策略
为了使connMgr.closeExpiredConnections();起到作用,我们需要指定连接keep alive策略,来告诉httpClient,哪些连接大概什么时候会过期,你可以关闭他们。下面是一个设置keep alive 策略的例子:
ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() { public long getKeepAliveDuration(HttpResponse response, HttpContext context) { // Honor 'keep-alive' header HeaderElementIterator it = new BasicHeaderElementIterator( response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { HeaderElement he = it.nextElement(); String param = he.getName(); String value = he.getValue(); if (value != null && param.equalsIgnoreCase("timeout")) { try { return Long.parseLong(value) * 1000; } catch(NumberFormatException ignore) { } } } HttpHost target = (HttpHost) context.getAttribute( HttpClientContext.HTTP_TARGET_HOST); if ("www.naughty-server.com".equalsIgnoreCase(target.getHostName())) { // Keep alive for 5 seconds only return 5 * 1000; } else { // otherwise keep alive for 30 seconds return 30 * 1000; } } }; CloseableHttpClient client = HttpClients.custom() .setKeepAliveStrategy(myStrategy) .build();
这个例子指明在访问www.naughty-server.com和其他未知服务器时的keeplive为一个固定值,如果服务器返回keeplive过期时间,则通过服务器告诉客户端该连接大概什么时候过期(注意这不是一个标准的http协议,不是所有服务器都支持)。
总结
如 果httpClient是访问单一的地址(如rpc请求),通过与服务器配置配合能够更高效的利用客户端的连接池,例如以tomcat为例,设置 maxKeepAliveRequests为-1则可以使该连接可以请求无限次数,而设置keepAliveTimeout为一个较大的时间则可以让客户 端更有效的利用连接池中的连接。凡事都有前提,如果目标tomcat即用于rpc调用,又用于服务正常连接请求的话,则上面优化反而会大量消耗服务器资 源。这时可以讲这两类服务拆分成两个tomcat进行分别处理。另外,如果在服务器前面配有代理的话(apache,nginx),则还需视情况设置代理 的keepAlive策略以提高利用率。
相关推荐
在这个“springboot-keepalive设置测试”项目中,我们将关注的是如何在Spring Boot应用中配置和测试HTTP长连接(keepalive)功能,以优化服务器与客户端之间的通信效率。 HTTP长连接,也被称为持久连接,允许TCP...
5. **重试策略**:当网络不稳定或服务器出现问题时,HttpClient可以配置重试策略,自动重新发送失败的请求。 6. **响应处理**:HttpClient提供了解析和处理服务器响应的能力,包括响应状态码、头部信息、响应体等。...
Tomcat作为一个流行的开源Java应用服务器,提供了多种数据源配置方式,以支持Web应用程序高效、安全地访问数据库。在这个主题中,我们将深入探讨如何配置数据源,以及它在Tomcat中的工作原理。 数据源(DataSource...
1.高效简单池化的HttpClient工具类,提供单元测试用列。 2.支持基于SpringBoot 2.1.x的自动装载模块,引用依赖即可使用。 3.公司几十个项目都使用该工具类访问第三方的Http/Https+json协议接口。 4.经过上市公司多个...
【描述】:“本教程将指导你如何利用Apache HttpClient 4.1实现对HTTPS服务的访问,首先需要在Tomcat服务器上配置SSL支持。我们将涵盖SSL证书的生成、Tomcat服务器的SSL配置以及HttpClient的使用。” 【标签】:...
8. **关闭连接**:记得在完成请求后关闭HttpClient和响应实体,以释放资源。 9. **错误处理**:处理可能出现的异常,如网络问题、认证失败或证书问题。 通过这些步骤,我们可以使用Apache HttpClient库安全地与443...
此外,还提及了 HttpClient能够以插件式的自定义认证方案以及支持持久连接等高级功能。 在基础知识方面,文档首先讲解了环境的准备,包括下载HttpClient包并将其导入到工程中的具体步骤。随后介绍了几个主要的类,...
配置 Tomcat 服务器支持 SSL 配置 Tomcat 服务器支持 SSL 是为了开启 Tomcat 的安全认证通道,从而确保数据的安全传输。在某些项目中,可能需要使用 SSL 加密来保护数据的安全。 首先,需要准备好生成的证书...
本文将深入探讨如何在WPF应用中利用HttpClient进行异步操作,以避免阻塞主线程,提高用户体验。 首先,让我们了解WPF的基本架构。WPF是一个用于构建桌面应用程序的框架,它提供了丰富的用户界面功能。为了保持用户...
- **连接管理**:通过`HttpConnectionManager`,HttpClient可以管理多个并发连接,实现高效的连接复用,降低网络延迟。 - **请求和响应处理**:HttpClient提供了`HttpRequestExecutor`和`HttpResponseHandler`接口...
HttpClient库允许开发者执行各种HTTP方法(如GET、POST、PUT等),处理重定向、认证、cookie管理等复杂网络交互,同时提供了线程安全和高效的连接管理机制。这个库在处理Web服务API、爬虫程序或任何需要与HTTP服务器...
在IT行业中,网络通信是应用程序之间交互的重要方式。...正确理解和应用HttpClient的各种特性和配置,能够帮助我们构建高效、可靠的网络通信方案。在实际开发中,还需要根据具体项目需求进行适当的调整和优化。
在实际使用HttpClient时,需要根据项目需求选择合适的版本,理解其工作原理,正确配置和使用相关组件,以实现高效且可靠的HTTP通信。同时,及时关注Apache HttpClient的更新,以便利用新特性并修复已知问题。
- **连接管理**:HttpClient 提供了连接池管理器,可以复用已建立的连接,减少网络延迟,提高效率。 - **HTTP 方法**:支持 GET、POST、PUT、DELETE 等多种 HTTP 方法,以及 HEAD、OPTIONS、TRACE 等其他标准方法...
在Java编程中,HttpClient是一个非常重要的库,常用于执行HTTP请求。当涉及到HTTPS接口调用时,HttpClient...通过实践和理解这些文件,开发者可以更好地掌握HttpClient的使用,从而编写出高效、安全的网络请求代码。
在文档中,这一点被明确地指出,以帮助用户正确地利用HttpClient。 文档中提到了HttpClient的基础知识,包括以下几个方面: 1. 请求执行(Request Execution) - HTTP请求(HTTP Request):讲述了如何构建和发送...
通过HttpClient实例,我们可以配置连接管理、重试策略、超时设置等高级特性。 2. **HttpHost对象**:表示目标服务器的信息,包括主机名、端口号和协议类型(HTTP或HTTPS)。 3. **HttpRequest与HttpResponse**:...
2. 空闲连接回收:设置合理的KeepAlive策略,防止内存泄露。 3. SSL证书问题:处理自签名或不受信任的证书,可能需要自定义SSLSocketFactory。 4. 并发处理:在多线程环境中,需正确管理和同步HttpClient实例。 总...
配置HttpClient时,可以定制连接管理器、超时设置、重试策略等。例如,使用`PoolingHttpClientConnectionManager`可以控制连接池大小,避免频繁创建新连接。`RequestConfig`允许你设置连接、读取和 socket 超时。 ...