我的编程空间,编程开发者的网络收藏夹
学习永远不晚

HttpClient 出现 failed to respond 异常解决

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

HttpClient 出现 failed to respond 异常解决

今天碰到一个问题,httpclient 在使用线程池时,偶尔出现 NoHttpResponseException 异常。

httpclient org.apache.http.NoHttpResponseException: host:端口 failed to respond

经过一轮排查可能的原因是两个:我们属于第二个


原因

直接原因:服务器收到请求以后,不处理直接丢弃。
实际情况:
1.当服务端由于负载过大等情况发生时,可能会导致在收到请求后无法处理(比如没有足够的线程资源),会直接丢弃链接而不进行处理。此时客户端就会报错:NoHttpResponseException。
解决建议:
重试

客户端与服务端建立的请求在服务端已经失效。(例如:服务端 springboot 内置 tomcat 默认 keepAliveTimeout :20s,客户端自定义 keepAliveTimeout :30s,客户端连接池中取出的空闲连接可能已经被服务端失效,再次从连接池拿该失效连接进行请求时,就会报错。)
解决建议:
检查并关闭失效连接

解决方案

设置重试策略,这种要求服务端端接口是幂等的,但是业务反馈实际上请求的业务已经执行,所以我们不能重试。

HttpClient httpClient = HttpClients.custom()
        .setConnectionManager(connectionManager)
         // 问题一解决方案:设置重试
        .setRetryHandler(new MyRetryHandler()) 
         // 问题二解决方案:调整 keepAliveTimeout,这样无法复用长连接
        .setKeepAliveStrategy(myStrategy)
        .setDefaultRequestConfig(requestConfig)
        .setDefaultConnectionConfig(connectionConfig)
        .build();

设置校验机制(不百分百有效)

当每次拿到链接后会校验链接是否还建立,在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();    }

参考:

https://www.cnblogs.com/zjdxr-up/p/14530875.html

HttpComponents HttpClient连接池(10)-使用建议 - 腾讯云开发者社区-腾讯云 

HttpClient的详细配置指南(基于HttpClient 4.3.5)_chenghui7393的博客-CSDN博客

来源地址:https://blog.csdn.net/qq_35789269/article/details/127236547

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

HttpClient 出现 failed to respond 异常解决

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

APPLICATION FAILED TO START 异常报错原因及解决方案

文章目录 一、APPLICATION FAILED TO START 异常报错原因分析1. 异常报错描述: 二、端口号被占用(Port 8080 was already in use) 导致的 APPLICATION FAILE
2023-08-17

出现SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“.如何解决

今天小编给大家分享一下出现SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“.如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享
2023-07-02

解决 git clone 时出现Failed to connect to 127.0.0.1 port 1573问题

今天去拉一个仓库代码,往常都是一下就拉下来了,今天却报错,报错信息如下: 原因:这种情况是因为代理在git中配置的,但是本身环境就有SSL协议了,所以取消git的https或者http代理即可 方法如下: git config --glob
2023-08-30

出现java.lang.NoSuchMethodException异常如何解决

今天小编给大家分享一下出现java.lang.NoSuchMethodException异常如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面
2023-07-05

出现java.lang.NoSuchMethodException异常的解决(靠谱)

这篇文章主要介绍了出现java.lang.NoSuchMethodException异常的解决方案(靠谱),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-15

Android ListView出现异常解决办法

Android ListView 异常解决办法: ListView:The content of the adapter has changed but ListView did not receive a notification使用Li
2022-06-06

Spring @Cacheable redis出现异常如何解决

Spring @Cacheable redis出现异常如何解决?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。原因分析我们是通过@EnableCaching进行缓
2023-06-06

python中出现FileNotFoundError异常如何解决

本篇文章给大家分享的是有关python中出现FileNotFoundError异常如何解决,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。python的五大特点是什么python
2023-06-14

MySQL出现Waitingfortablemetadatalock异常的解决方法

当MySQL使用时出行Waitingfortablemetadatalock异常时该怎么办呢?这篇文章就来和大家讲讲解决办法,感兴趣的小伙伴可以了解一下
2023-05-15

使用Eclipse时出现报错(Failed to create the Java ..)如何解决

这期内容当中小编将会给大家带来有关使用Eclipse时出现报错(Failed to create the Java ..)如何解决,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Eclipse 开发java
2023-05-31

Python中出现异常重试如何解决

这篇文章给大家介绍Python中出现异常重试如何解决,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。原先的流程:def crawl_page(url): pass def log_error(ur
2023-06-17

Java中出现java.lang.IllegalStateException异常错误的解决

这篇文章主要介绍了Java中出现java.lang.IllegalStateException异常错误的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-01-09

java项目中出现异常如何解决

本篇文章为大家展示了java项目中出现异常如何解决,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象
2023-06-14

编程热搜

目录