帮助文档
专业提供香港服务器、香港云服务器、香港高防服务器租用、香港云主机、台湾服务器、美国服务器、美国云服务器vps租用、韩国高防服务器租用、新加坡服务器、日本服务器租用 一站式全球网络解决方案提供商!专业运营维护IDC数据中心,提供高质量的服务器托管,服务器机房租用,服务器机柜租用,IDC机房机柜租用等服务,稳定、安全、高性能的云端计算服务,实时满足您的多样性业务需求。 香港大带宽稳定可靠,高级工程师提供基于服务器硬件、操作系统、网络、应用环境、安全的免费技术支持。
服务器资讯 / 香港服务器租用 / 香港VPS租用 / 香港云服务器 / 美国服务器租用 / 台湾服务器租用 / 日本服务器租用 / 官方公告 / 帮助文档
HttpClient 出现 failed to respond 异常解决
发布时间:2024-02-28 03:33:47   分类:帮助文档
HttpClient 出现 failed to respond 异常解决 今天碰到一个问题,httpclient 在使用线程池时,偶尔出现 NoHttpResponseException 异常。 httpclient org.apache.http.NoHttpResponseException: host:端口 failed to respond 经过一轮排查可能的原因是两个:我们属于第二个 原因 直接原因:服务器收到请求以后,不处理直接丢弃。 实际情况: 1.当服务端由于负载过大等情况发生时,可能会导致在收到请求后无法处理(比如没有足够的线程资源),会直接丢弃链接而不进行处理。此时客户端就会报错:NoHttpResponseException。 解决建议: 重试 2.客户端与服务端建立的请求在服务端已经失效。(例如:服务端 springboot 内置 tomcat 默认 keepAliveTimeout :20s,客户端自定义 keepAliveTimeout :30s,客户端连接池中取出的空闲连接可能已经被服务端失效,再次从连接池拿该失效连接进行请求时,就会报错。) 解决建议: 检查并关闭失效连接 解决方案 1.设置重试策略,这种要求服务端端接口是幂等的,但是业务反馈实际上请求的业务已经执行,所以我们不能重试。 HttpClient httpClient = HttpClients.custom()         .setConnectionManager(connectionManager)          // 问题一解决方案:设置重试         .setRetryHandler(new MyRetryHandler())           // 问题二解决方案:调整 keepAliveTimeout,这样无法复用长连接         .setKeepAliveStrategy(myStrategy)         .setDefaultRequestConfig(requestConfig)         .setDefaultConnectionConfig(connectionConfig)         .build(); 2、设置校验机制(不百分百有效) 当每次拿到链接后会校验链接是否还建立,在validateAfterInactivity时间内不重复校验(默认两秒),比如,validateAfterInactivity设置的是5s,上次使用链接是在1s前,则不会校验直接使用 httpClientConnectionManager.setValidateAfterInactivity(5000); HttpClient连接池-使用建议 对于 httpclient 连接池使用一般考虑以下几点: 向连接池申请连接的超时时间连接建立的超时时间,即 socket 进行 3 次握手建立连接的超时时间连接超时时间,即 socket 读写超时时间设置最大 redirect 次数是否开启可用性检查global 连接池中最大的连接数individual route 连接池中最大的连接数请求重试次数设置ssl 请求的证书 trust 策略和 cn host name 验证策略开启对于空闲连接以及过期连接的清理,设置空闲连接的时长是否重用池化对象以及使用长连接 我们通过如下代码设置上述 items : RequestConfig requestConfig = RequestConfig.custom() .setConnectionRequestTimeout(10000)//设置连接池申请连接的超时时间,默认-1为无限时间 .setConnectTimeout(5000)//设置socket进行3次握手建立连接的超时时间 .setSocketTimeout(8000)//设置连接超时时间,即socket读写超时时间 .setMaxRedirects(50)//设置最大的redirect次数,默认为50 .setStaleConnectionCheckEnabled(Boolean.TRUE)//设置开启可用性检查,默认不开启 .build(); CloseableHttpClient htttpClient = HttpClients.custom() .setDefaultRequestConfig(requestConfig) .setMaxConnPerRoute(50)//设置individual route连接池中最大的连接数,默认为2 .setMaxConnTotal(500)//设置global连接池中最大的连接数,默认为20 .setConnectionTimeToLive(-1, TimeUnit.MICROSECONDS)//设置连接池中连接存活时间,默认-1代表无限存活,连接使用之后由response header "Keep-Alive: timeout"决定。 .evictIdleConnections(60000, TimeUnit.MILLISECONDS)//开启空袭连接清理线程,设置连接池中连接最大空闲时间,以及连接清理线程的sleep时间,默认为10秒 .evictExpiredConnections()//开启过期连接清理线程,过期时间默认为-1,连接使用后由response header "Keep-Alive: timeout"决定。 //.setRetryHandler(retryHandler)//设置重试策略,默认3次重试 //.setSSLContext(sslContext)//设置ssl请求上下文 //.setSSLHostnameVerifier(hostnameVerifier)//设置ssl证书cn host name验证策略,默认为验证cn host name .build(); 如果希望重用池化对象并且保持长连接,那么务必请调用 EntityUtils 类之中的静态方法toByteArray(),toString(),consume(),consumeQuietly()等。如果不希望重用池化对象,同时也不希望使用长连接,那么请调用 CloseableHttpResponse 的close() 方法。另外我们也会经常使用 Spring 的 RestTemplate 来发送 https 请求,对于 RestTemplate 一般也是会去整合 Apache HttpComponents HttpClient 组件,所以在使用 RestTemplate 的时候也请考虑以上各个 items 的设置。 原理篇     1、org.apache.http.conn.HttpClientConnectionManager​​​​​​​ 线程安全。     httpclient中给出的实现类有两个:         1)org.apache.http.impl.conn.BasicHttpClientConnectionManager * A connection manager for a single connection. This connection manager maintains only one active * connection. Even though this class is fully thread-safe it ought to be used by one execution * thread only, as only one thread a time can lease the connection at a time.         文档讲的很明白的,单链接管理类,对每个HttpRoute只保持一个有效链接,在实际项目中没有使用经验,不做评论。 PoolingHttpClientConnectionManager中的两个常用属性: PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE); connectionManager.setMaxTotal(DEFAULT_SOCKET_MAX_TOTAL);             MaxTotal:整个连接池的最大连接数             DefaultMaxPerRoute:单个HttpRoute最大连接数,项目中假如只连接一个route那么可以设置为等于MaxTotal 2、org.apache.http.client.config.RequestConfig 这个类属性很多,所以使用了典型的构建器模式,通过内部类RequestConfig.Builder的build()方法来创建RequestConfig对象。             一段典型的创建RequestConfig的代码 RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT) .setConnectionRequestTimeout(DEFAULT_REQUEST_TIMEOUT) .setSocketTimeout(DEFAULT_SOCKET_TIMEOUT) .setStaleConnectionCheckEnabled(true).build();             几个常用的属性:                 ConnectTimeout:建立连接的超时时间                 ConnectionRequestTimeout:从连接池中获取连接超时时间                 SocketTimeout:socket传输超时时间                 StaleConnectionCheckEnabled:是否启用检查失效连接,这个属性在4.4版本中被PoolingHttpClientConnectionManager中的#setValidateAfterInactivity(int)替换掉了。 所以,这里是我们可以用到的。 3、org.apache.http.impl.client.HttpClientBuilder 使用HttpClientBuilder类的静态方法create()创建HttpClientBuilder对象,将我们之前创建的PoolingHttpClientConnectionManager和RequestConfig对象通过setter方法设置给HttpClientBuilder,调用HttpClientBuilder对象的工厂方法build()来构建我们需要使用的httpclient对象,一段典型示例代码如下: CloseableHttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager) .setDefaultRequestConfig(requestConfig).build();     在构建我们的httpclient对象之前,HttpClientBuilder中还有其他的一些配置需要我们注意,         setRetryHandler:设置重试策略,httpclient对象默认使用org.apache.http.impl.client.DefaultHttpRequestRetryHandler类维护的本类静态实例INSTANCE,重试3次,并且在请求已经完整发送的情况下不重试。         disableAutomaticRetries:禁用自动重试,如果此项设置为true,那么将忽略已经设置的RetryHandler。         另外还有重定向策略,keepalive策略,cookiestore等等,可以根据项目需要进行设置。 三、项目中使用httpclient​​​​​​​  1、HttpClient实例:     httpclient中使用的PoolingHttpClientConnectionManager是线程安全的,httpclient也是线程安全的,在我们的项目中可以只维护一个httpclient对象,频繁的创建httpclient对象并不明智。通过设置PoolingHttpClientConnectionManager中的属性来保证性能。     2、快速创建默认配置的httpclient对象:     使用4.3版本中的org.apache.http.impl.client.HttpClients类的工厂方法来创建。 CloseableHttpClient closeableHttpClient = HttpClients.createDefault();      以上方法创建的httpclient对象,所有配置都将使用默认值:         PoolingHttpClientConnectionManager的默认配置             DefaultMaxPerRoute=2             MaxTotal=20         RequestConfig的默认配置: this.staleConnectionCheckEnabled = false; this.redirectsEnabled = true; this.maxRedirects = 50; this.relativeRedirectsAllowed = true; this.authenticationEnabled = true; this.connectionRequestTimeout = -1; this.connectTimeout = -1; this.socketTimeout = -1; this.contentCompressionEnabled = true; 3、详细的自定义配置创建httpclient对象,以下为一段示例代码,其中添加了https信任所有证书的操作 ​​​​​​​  private static final int DEFAULT_CONNECT_TIMEOUT = 2000;     private static final int DEFAULT_REQUEST_TIMEOUT = 1000;     private static final int DEFAULT_SOCKET_TIMEOUT = 10000;     private static final int DEFAULT_SOCKET_MAX_TOTAL = 200;     private static final int DEFAULT_MAX_PER_ROUTE = 200;     private CloseableHttpClient httpClient;     @PostConstruct     public void init() {         SSLConnectionSocketFactory sslsf = null;         final SSLContext sslcontext;         try {             sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {                 @Override                 public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {                     return true;                 }             }).build();             sslsf = new SSLConnectionSocketFactory(sslcontext,                     SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);         } catch (final SecurityException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException ignore) {         }         final Registry sfr = RegistryBuilder.create()                 .register("http", PlainConnectionSocketFactory.getSocketFactory())                 .register("https", sslsf != null ? sslsf : SSLConnectionSocketFactory.getSocketFactory())                 .build();         PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(sfr);         connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);         connectionManager.setMaxTotal(DEFAULT_SOCKET_MAX_TOTAL);         RequestConfig requestConfig = RequestConfig.custom()                 .setAuthenticationEnabled(false)                 .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT)                 .setConnectionRequestTimeout(DEFAULT_REQUEST_TIMEOUT)                 .setSocketTimeout(DEFAULT_SOCKET_TIMEOUT)                 .setStaleConnectionCheckEnabled(true).build();         //默认重试策略,重试3次         httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager)                 .setDefaultRequestConfig(requestConfig).build();     } 参考: 1、https://www.cnblogs.com/zjdxr-up/p/14530875.html 2、HttpComponents HttpClient连接池(10)-使用建议 - 腾讯云开发者社区-腾讯云  3、HttpClient的详细配置指南(基于HttpClient 4.3.5)_chenghui7393的博客-CSDN博客
香港云服务器租用推荐
服务器租用资讯
·主机测评:如何选择最合适的主机服务
·中文域名的ping操作详解,推荐2025年使用最新工具进行解析
·只有域名怎么备案,如何在没有服务器的情况下完成备案呢?只需向服务商提交信息就能开启备案流程。
·怎么转发网址:哪里有教你如何操作网址转发的方法?
·怎么选择php版本:最全面的PHP版本选择指南与实用建议
·怎么申请com域名?只需了解关键步骤,让你轻松注册理想域名。
·怎么购买IP地址?购买IP地址的步骤与注意事项详解及推荐的服务提供商介绍
·怎么防御流量攻击:哪里有有效的应对策略?
·怎么查域名dns:如何获取和解析DNS记录
服务器租用推荐
·美国服务器租用
·台湾服务器租用
·香港云服务器租用
·香港裸金属服务器
·香港高防服务器租用
·香港服务器租用特价