话说Connect reset异常
程序员文章站
2022-05-06 14:33:44
...
起因是这样的,线上log经常出现Connection Reset异常,从堆栈上分析是solr进行sharding request时发生的,solr部署在tomcat上。从现场来看,原因很明白Server端发出RST包。但具体原因是什么就得经过一番分析了,
经过google百度以及和网友沟通,发现会有以下场景导致RST:
1. 设置SoLinger,并设置停留时间为0
显然不是这样的场景,如是则会经常出现,而不是偶尔出现。还有其他的吗?我翻看了一下TCP/IP详解,TCP的连接与终止以及复位报文段。有点收获但还是没有看太懂,呵呵答案就在书上,也许没有沉下心去,一开始并没有书上介绍套出问题的场景。后来看到oracle的一篇文章http://docs.oracle.com/javase/1.5.0/docs/guide/net/articles/connection_release.html.
发现异常关闭非常适合出现问题的场景。啥叫异常关闭呢,正常的close是四次挥手
例如客户端执行close的时候,发出FIN,告诉对端我不再接受和发送数据,而对端也应该由应用程序调用close结束链接,也许你会说发出FIN只是告诉对端不再发送数据还能接收数据,事实上也是可以的,这样的关闭叫做半关闭,通过调用shutdown方法来实现。
solr为什么会遇到这样的问题,httpclient为了减少链接的建立开销使用connection manager的连接池管理链接,我们知道虽然Http1.1支持keep alive,但仍有条件限制,例如keepalivetimeout以及keepalive的个数。当tomcat进行keepalive的connectin timeout处理的处理的,只是单方面的close,对端趟在连接池中的connection并不知道也不会执行相应的close,恰巧这时候有一个reuest使用这个connection发出请求,这一点特别重要,还是能发送数据的,最初的时候我以为服务端close了客户端就不能再使用conneciton发送数据了。服务端不会读取client端发过来的数据坚决执行关闭,这时候这个关闭就是RST而不是FIN了。
B's TCP stack knows that some data is effectively lost and it will forcibly terminate with RST rather than use the orderly
FIN
procedure.
有两种这样的场景:
1. A向B 发送数据,B的应用执行close,而这时A试图继续发而不是由应用调用close。
2. A向B发送数据,B不做任何处理,不读取任何数据坚决地close,这时候这个close发的就是RST。
我写了一段代码来模拟以上两种情况
Server
public static void run(){ try{ //InetSocketAddress address = new InetSocketAddress("10.58.99.27", 9090); //InetAddress address = InetAddress.getByName("10.58.99.27"); ServerSocket serverSocket = new ServerSocket(9090,1); ExecutorService threadPool = Executors.newCachedThreadPool(); // for(int i = 0; i < 1;i++){ // new Thread(new BioHttpServer.Connector()).start(); // } // latch.countDown(); while(true){ Socket client = serverSocket.accept(); Thread.sleep(1000);//调整这个时间 如调整为100 则为情况1 1000为情况2 client.close(); // client.shutdownOutput(); // if(isDistribute){ // threadPool.execute(new SocketProcessor(client)); // }else{ // new SocketProcessor(client).run(); // } } }catch(Exception e){ e.printStackTrace(); }finally{ } }
Client
try { Socket client = new Socket("10.58.99.74", 9090); // client.setSoTimeout(5000); System.out.println(client); InputStream ins =client.getInputStream(); int i = 0; // System.out.println(ins.read()); while(i++ < 100000){ client.getOutputStream().write(64); } System.out.println(ins.read()); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
上一篇: HashMap无序与LinkedHashMap有序
下一篇: Oracle物化视图的使用
推荐阅读
-
解决Docker中的error during connect异常情况
-
即时通讯开发中报的异常:-- caused by: java.net.ConnectException: failed to connect to /127.0
-
异常代码:2003 can't connect to MySQL server on '*'(10061)
-
使用curl报couldn't connect to host异常
-
异常代码:2003 can't connect to MySQL server on '*'(10061)
-
SELinux导致PHP连接MySQL异常Can't connect to MySQL server的解决方法_MySQL
-
关于curl时提示“ couldn't connect to host ”的异常信息
-
异常代码:2003 can't connect to MySQL server on '*'(10061)
-
SELinux导致PHP连接MySQL异常Can't connect to MySQL server的解决方法_MySQL
-
使用curl报couldn't connect to host异常