记一次NoHttpResponseException问题排查
上传文件程序会有一定的概率提示错误,错误率大概在1%以下,错误信息是:org.apache.http.NoHttpResponseException , s3-us-west-1.amazonaws.com:80 failed to respond,看着是上传到S3的过程中发送了网络错误?

通过查阅资料,发现了一篇比较好的文章:一次NoHttpResponseException问题分析解决。这个文章的观点是会发生这个错误的原因是服务端关闭了连接,而客户端还在使用该连接,导致服务端响应RST报文,客户端收到RST报NoHttpResponseException异常。
为了说明这个场景,就要提一下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时间
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问题排查的更多相关文章
- 坑爹坑娘坑祖宗的87端口(记一次tomcat故障排查)
原贴如下 坑爹坑娘坑祖宗的87端口(记一次tomcat故障排查) 虽然我用的是PHPstudy部署的dedecms,还是一样栽倒这个坑里了. 总结经验:本地测试使用8000~9000的端口比较安全.
- 记一次用arthas排查jvm中CPU占用过高问题
记一次使用arthas排查jvm中CPU占用过高问题.这工具屌爆了 碾压我目前使用的全部JVM工具. 安装 小试 curl -O https://arthas.aliyun.com/arthas-bo ...
- 记一次tomcat故障排查(转)
1~1024之间的端口号是保留端口,通常是为特定目的预留的.虽然你的问题不是由于保留端口引起的,但是仍然建议你不要随意使用保留端口作为自定义服务的端口,如果你能早早遵循这一规则压根就不会遇到这个问题. ...
- 记一次jvm异常排查及优化
为方便自己查看,根据工作遇到的问题,转载并整理以下jvm优化内容 有次接到客服反馈,生产系统异常,无法访问.接到通知紧急上后台跟踪,查看了数据库死锁情况--正常,接着查看tomcat 内存溢出--正常 ...
- 【问题记录】记一次ConnectionTimeout问题排查
最近做性能测试时,发现连接第三方系统时会有约1%的交易提示如下错误 nested exception is org.apache.commons.httpclient.ConnectTimeoutEx ...
- 记一次Windb死锁排查
正在开会,突然线上站点线程数破千.然后一群人现场dump分析. 先看一眼线程运行状态 !eeversion 发现CPU占用并不高,19%,937条线程正在运行. 看看他们都在干什么. ~* e !cl ...
- 记一次OOM问题排查过程
上周运维反馈线上程序出现了OOM,程序日志中的输出为 Exception in thread "http-nio-8080-exec-1027" java.lang.OutOfMe ...
- 记一次使用windbg排查内存泄漏的过程
一.背景 近期有一个项目在运行当中出现一些问题,程序顺利启动,但是观察一阵子后发现内存使用总量在很缓慢地升高, 虽然偶尔还会往下降一些,但是总体还是不断上升:内存运行6个小时候从33M上升到80M: ...
- 记一次oom问题排查
大家好,我是大彬~ 今天给大家分享最近出现的OOM问题. 上周五早上,测试同学反馈测试环境的子系统服务一直超时,请求没有响应. 收到这个问题之后,我有点纳闷,最近这个系统也没有改动代码逻辑,怎么会突然 ...
随机推荐
- JAVA-替换html中图片的路径-从html代码中提取图片路径并下载(完整版)
transHtml方法实现提取网络图片中得图片路径,将其重新下载到本地,并替换html中原来得路径 package com.googosoft.until; import java.io.Buffer ...
- 7,请描述下cookies,sessionStorage和localStorage的区别
7,请描述下cookies,sessionStorage和localStorage的区别 首先,cookie是网站为了标识用户身份而储存在用户本地终端(client side,百科: 本地终端指与计算 ...
- Activiti工作流学习之概述(一)
一.工作流介绍 我第一次听到这个词,是蒙逼的,再看百度百度,更傻眼了,完全说的不像人话啊,举几个生活中的例子,就明白多了比如:请假.报销等等,如果文字太过抽象,请看图: 二.工作流引擎 Process ...
- idea垂直分屏
1.找到分屏功能 搜索keymap(注意大小写): 2.Split Vertically 垂直分屏/Split Horizontally 水平分屏 3.添加快捷方式
- 转入软工后第一节java课的作业
这个作业,鸽了好久.本来大家都在中秋前发了,我摸摸索索加上各种缓慢的学习,终于是将他做完了. 做完之后,java最基本的输入输出功能都基本学习到了.下面附上代码: import java.util.* ...
- 【原】python总结
python3浅拷贝和深拷贝:https://www.jianshu.com/p/c7e72fcad407
- 第七节:Vuejs路由交互及后台系统路由案例
一. 简介 1.路由的概念 路由的本质就是一种对应关系,比如说我们在url地址中输入我们要访问的url地址之后,浏览器要去请求这个url地址对应的资源.那么url地址和真实的资源之间就有一种对应的关系 ...
- 测试者出的APP测试面试题
测试者出的APP测试面试题 一.开场问题:(自由发挥) 1.请自我介绍一下: 2.为什么离开上一个公司呢? 3.做测试多久了?以前做过哪些项目?你们以前测试的流程是怎样的?用过哪些测试工具? 4.你觉 ...
- 软件架构,WEB - MVC,MVP,MVVM
参考 https://www.zhihu.com/question/20148405/answer/107071448 http://www.cnblogs.com/indream/p/3602348 ...
- Faster-RCNN Pytorch实现的minibatch包装
实际上faster-rcnn对于输入的图片是有resize操作的,在resize的图片基础上提取feature map,而后generate一定数量的RoI. 我想首先去掉这个resize的操作,对每 ...