NoHttpResponseException问题排查解决记录分析

 更新时间:2023年08月17日 09:36:36   作者:木杉  
这篇文章主要为大家介绍了NoHttpResponseException问题排查解决记录分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

错误提示

上传文件程序会有一定的概率提示错误,错误率大概在1%以下,错误信息是:

org.apache.http.NoHttpResponseException , s3-us-west-1.amazonaws.com:80 failed to respond

看着是上传到S3的过程中发送了网络错误?

通过查阅资料,发现了一篇比较好的文章:一次NoHttpResponseException问题分析解决。这个文章的观点是会发生这个错误的原因是服务端关闭了连接,而客户端还在使用该连接,导致服务端响应RST报文,客户端收到RST报NoHttpResponseException异常。

Keepalive机制

为了说明这个场景,就要提一下Keepalive机制。Keepalive是HTTP的连接复用机制,在HTTP1.0时代,每个请求经过三次握手后,只会传输一次HTTP请求和响应报文后,就进入四次挥手关闭连接了。而TCP建立连接和关闭连接的代价是比较大的,导致HTTP1.0的通道利用率较低,时延较高。针对这个问题,退出了Keepalive机制,一个TCP连接建立后,可以在上面发送多个HTTP报文,只有这个TCP连接的空闲时间达到超时时间,才会被关闭。HTTP1.1默认开启Keepalive。这里的关闭行为可能发生在客户端和服务端,比如客户端的Keepalive超时时间更短,则客户端就会先关闭连接,如果服务端配置的Keepalive超时时间更短,则服务端就会先关闭连接。

乍看起来无论那一边关闭连接都没什么问题,但是还是有细节需要注意。比如服务端关闭连接,发送FIN包,在这个FIN包发送但是还未到达客户端期间,客户端如果继续复用这个TCP连接,发送HTTP请求报文的话,服务端会因为在四次挥手期间不接收报文而发送RST报文给客户端,客户端收到RST报文就会提示异常。

根据上面的理论知识,可以推测org.apache.http.NoHttpResponseException , s3-us-west-1.amazonaws.com:80 failed to respond这个错误发生的原因是因为我的程序的HttpClient的Keepalive时间大于S3服务器的,导致S3服务端关闭连接时,可能发生异常。我们做个试验看看。

观察AWS S3服务端的Keepalive时间

首先写一个简单程序观察一下AWS S3服务端的Keepalive时间

String url = "一个可以访问的S3下载地址";
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet(url);
httpClient.execute(request, response -> {
    String content = EntityUtils.toString(response.getEntity());
    System.out.println(content);
    return content;
});
Thread.sleep(99999);

Wireshark抓包观察HTTP响应报文后,经过多久进入四次挥手:

可以看出服务端发送FIN包距离上一个请求的时间大概是23秒,也就是AWS S3服务端的Keepalive时间大致为23秒。

接着我们模拟客户端在服务端关闭连接的同时发送请求的场景,看看能否复现NoHttpResponseException错误:

String url = "http://s3-us-west-1.amazonaws.com/sdpcs-prod-awsca/88ea9001-bad0-4b46-86e5-e6bc518c9fdc?Expires=1718171230&response-content-type=image/jpeg&response-cache-control=max-age%3D157680000&AWSAccessKeyId=AKIAI7P7PYLVYWVVYTLQ&Signature=iCeE6%2FIHtxmOarOc3Q1hUowWqDc%3D";
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet(url);
for (int i = 0; i < 100000; i++) {
    httpClient.execute(request, response -> {
        String content = EntityUtils.toString(response.getEntity());
        System.out.println(content);
        return content;
    });
    Thread.sleep(23000);
}

多执行几次,就能复现出NoHttpResponseException错误:

六月 14, 2019 2:09:14 下午 org.apache.http.impl.execchain.RetryExec execute
信息: I/O exception (org.apache.http.NoHttpResponseException) caught when processing request to {}->http://s3-us-west-1.amazonaws.com:80: The target server failed to respond
六月 14, 2019 2:09:14 下午 org.apache.http.impl.execchain.RetryExec execute
信息: Retrying request to {}->http://s3-us-west-1.amazonaws.com:80

分析抓包

可以看到2400号请求距离上一个请求23秒,然后在服务端还未收到2400号请求时,客户端就收到了服务端发来的FIN请求,进入了四次挥手流程。然后当服务端收到2400号请求后,响应RST请求,导致客户端提示错误。

HttpClient提供了关闭空闲连接的功能

CloseableHttpClient httpClient = HttpClients.custom()
                .evictIdleConnections(5, TimeUnit.SECONDS)
                .build();

我们设置一个低于S3 Keepalive的时间再次执行,就不会出现NoHttpResponseException错误了。

除了在客户端设置小于服务端的Keepalive时间,还有一种做法是在出现NoHttpResponseException时进行重试,也是可以的,还可以减少TIME_WAIT数量。

以上就是NoHttpResponseException问题排查解决记录分析的详细内容,更多关于NoHttpResponseException问题排查的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot如何解析应用参数args

    SpringBoot如何解析应用参数args

    文章主要介绍了SpringBoot启动过程中如何解析`main`函数中的参数`args`,包括如何解析命令行参数、访问选项参数和非选项参数,接着,介绍了`ApplicationArguments`接口及其方法,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • Java如何实现批量打印条形码

    Java如何实现批量打印条形码

    这篇文章主要为大家详细介绍了如何基于 ZXing 库生成条形码位图,并利用 Java 打印服务(PrinterJob)将它们以网格方式批量打印到 A4 标签纸或标签纸格式,需要的小伙伴可以参考一下
    2025-05-05
  • Spring Boot2+JPA之悲观锁和乐观锁实战教程

    Spring Boot2+JPA之悲观锁和乐观锁实战教程

    这篇文章主要介绍了Spring Boot2+JPA之悲观锁和乐观锁实战教程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • springboot多环境配置方案(不用5分钟)

    springboot多环境配置方案(不用5分钟)

    这篇文章主要介绍了springboot多环境配置方案(不用5分钟),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • mybatis插件pageHelper实现分页效果

    mybatis插件pageHelper实现分页效果

    这篇文章主要为大家详细介绍了mybatis插件pageHelper实现分页效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • SpringBoot项目中使用缓存Cache的正确方法分享

    SpringBoot项目中使用缓存Cache的正确方法分享

    缓存可以通过将经常访问的数据存储在内存中,减少底层数据源如数据库的压力,从而有效提高系统的性能和稳定性。本文就来讲讲SpringBoot项目中使用缓存Cache的正确姿势吧
    2023-04-04
  • 详解Spring-Boot集成Spring session并存入redis

    详解Spring-Boot集成Spring session并存入redis

    这篇文章主要介绍了详解Spring-Boot集成Spring session并存入redis,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 详解java google Thumbnails 图片处理

    详解java google Thumbnails 图片处理

    这篇文章主要介绍了java google Thumbnails 图片处理的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java重入锁(ReentrantLock)从入门到源码深度解析

    Java重入锁(ReentrantLock)从入门到源码深度解析

    本文给大家介绍Java重入锁(ReentrantLock)从入门到源码深度解析,通过本文学习可以全方位地认识ReentrantLock,从基本概念到高级特性,从使用方式到源码剖析,从底层原理到实际应用,感兴趣的朋友跟随小编一起看看吧
    2026-02-02
  • idea install 时提示jdk的某个jar包的包不存在的问题

    idea install 时提示jdk的某个jar包的包不存在的问题

    这篇文章主要介绍了idea install 时提示jdk的某个jar包的包不存在的问题,本文给大家分享解决方法,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09

最新评论