读书人

话说Connect reset错误

发布时间: 2012-12-24 10:43:13 作者: rapoo

话说Connect reset异常

? ? ?起因是这样的,线上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是四次挥手话说Connect reset错误话说Connect reset错误例如客户端执行close的时候,发出FIN,告诉对端我不再接受和发送数据,而对端也应该由应用程序调用close结束链接,也许你会说发出FIN只是告诉对端不再发送数据还能接收数据,事实上也是可以的,这样的关闭叫做半关闭,通过调用shutdown方法来实现。话说Connect reset错误话说Connect reset错误? ?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();                }   
?

1 楼 zhanlanlubai921 2012-11-08 楼主我也遇到了这个问题,使用solrj过程中经常会发生Connection Reset这样的异常。
看完你的文章,觉得你描述问题成因很详细,但是却没有解决办法啊。
楼主最后是怎么解决这个问题的呢? 2 楼 xiaoZ5919 2012-11-08 方案一 关闭keepalive 保证了顺序关闭
方案二 假如solr host在tomcat上,把maxKeeplive设置大些,并设置timeout时间长些,这样类似伪的长连接。同时solrj基于httpclient并使用threadsafeconnectionmanger维持一个connection pool。把connection的有效期设置小于服务端的timeout。这样能避免再次使用半关闭的connection。
这是我当时提出的方案,由于某些原因我的方案并没有实施 你可以试试! 3 楼 xiaoZ5919 2012-11-08 xiaoZ5919 写道方案一 关闭keepalive 保证了顺序关闭
方案二 假如solr host在tomcat上,把maxKeeplive设置大些,并设置timeout时间长些,这样类似伪的长连接。同时solrj基于httpclient并使用threadsafeconnectionmanger维持一个connection pool。把connection的有效期设置小于服务端的timeout。这样能避免再次使用半关闭的connection。
这是我当时提出的方案,由于某些原因我的方案并没有实施 你可以试试!zhanlanlubai921 写道楼主我也遇到了这个问题,使用solrj过程中经常会发生Connection Reset这样的异常。
看完你的文章,觉得你描述问题成因很详细,但是却没有解决办法啊。
楼主最后是怎么解决这个问题的呢?

4 楼 zhanlanlubai921 2012-11-09 感谢楼主的细心回答,我试试看。有结果我及时反馈给你。 5 楼 zhanlanlubai921 2012-11-10 反馈结果如下:
第一种方案:关闭keepalive。 这样会影响tomcat的效率,在高并发压力情况下,不太好。因此只好舍弃。
第二种方案:在tomcat端可以进行设置,但是在solrj进行设置就比较麻烦,目前solrj没有提供可以设置connection live时间的方法。如果自己创建httpclient又要进行管理,麻烦了,也只好舍弃。

我的最终解决办法:大概原理是:当出现connection reset时,捕获住异常,再向服务端(可多个)请求一次,第二次访问应该就不会出现reset异常了。 6 楼 cuisuqiang 2012-11-15 我怎么听说是三次握手?
另外这无法解决网线中断引起的异常,心跳包都检测不到http://cuisuqiang.iteye.com/blog/1725348
不过还是感谢你的分享 7 楼 xiaoZ5919 2012-11-15 zhanlanlubai921 写道反馈结果如下:
第一种方案:关闭keepalive。 这样会影响tomcat的效率,在高并发压力情况下,不太好。因此只好舍弃。
第二种方案:在tomcat端可以进行设置,但是在solrj进行设置就比较麻烦,目前solrj没有提供可以设置connection live时间的方法。如果自己创建httpclient又要进行管理,麻烦了,也只好舍弃。

我的最终解决办法:大概原理是:当出现connection reset时,捕获住异常,再向服务端(可多个)请求一次,第二次访问应该就不会出现reset异常了。
好吧 这也是一个办法 8 楼 xiaoZ5919 2012-11-15 cuisuqiang 写道我怎么听说是三次握手?
另外这无法解决网线中断引起的异常,心跳包都检测不到http://cuisuqiang.iteye.com/blog/1725348
不过还是感谢你的分享
三次握手,四次挥手

读书人网 >编程

热点推荐