zookeeper 大量连接断开重连原因排查
转自:http://blog.csdn.net/hengyunabc/article/details/41450003?utm_source=tuicool&utm_medium=referral
问题现象
最后发现线上的zookeeper的日志zookeeper.out 文件居然有6G,后来设置下日志为滚动输出,参考:
http://blog.csdn.net/hengyunabc/article/details/19006911
但是改了之后,发现一天的日志量就是100多M,滚动日志一天就被冲掉了,这个不科学。
再仔细查看下日志里的内容,发现有很多连接建立好,马上又断开:
- 2014-11-24 15:38:33,348 [myid:3] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@1001] - Closed socket connection for client /10.0.0.3:47772 (no session established for client)
- 2014-11-24 15:38:33,682 [myid:3] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@197] - Accepted socket connection from /10.0.0.3:32119
- 2014-11-24 15:38:33,682 [myid:3] - WARN [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@349] - caught end of stream exception
- EndOfStreamException: Unable to read additional data from client sessionid 0x0, likely client has closed socket
- at org.apache.zookeeper.server.NIOServerCnxn.doIO(NIOServerCnxn.java:220)
- at org.apache.zookeeper.server.NIOServerCnxnFactory.run(NIOServerCnxnFactory.java:208)
- at java.lang.Thread.run(Thread.java:745)
- 2014-11-24 15:38:33,682 [myid:3] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@1001] - Closed socket connection for client /10.0.0.0:32119 (no session established for client)
从日志输出的时间来看,秒连秒断,非常诡异。
排查问题
用netstat查看网络连接状态
到client的服务器上查看连接的状态:
- netstat -antp | grep 2181
发现有很多TIME_WAIT状态的连接:
- tcp 0 0 10.0.0.3:44269 10.0.1.77:2181 TIME_WAIT -
- tcp 0 0 10.0.0.3:43646 10.0.1.77:2181 TIME_WAIT -
- tcp 0 0 10.0.0.3:44184 10.0.1.77:2181 TIME_WAIT -
- tcp 0 0 10.0.0.3:44026 10.0.1.77:2181 TIME_WAIT -
- tcp 0 0 10.0.0.3:43766 10.0.1.77:2181 TIME_WAIT -
但是TIME_WAIT状态的连接是看不到进程号的。搜索研究了下netstat的参数,发现没有办法输出TIME_WAIT状态的连接的pid,只好尝试其它的办法。
再用 jstack -l pid 来查看进程的线程栈,也没有发现什么异常的东东。查看到有几个zookeeper连接的线程,但也是正常状态。
再检查了机器的IO,CPU,内存,也没有异常的情况。
没找到什么有用的信息,只好再研究下netstat的参数:
发现用 netstat -ae 输出了一些信息:
- tcp 0 0 10.0.0.3:41772 10.0.1.77:eforward TIME_WAIT root 0
- tcp 0 0 10.0.0.3:41412 10.0.1.77:eforward TIME_WAIT root 0
- tcp 0 0 10.0.0.3:24226 10.0.1.77:2181 TIME_WAIT root 0
- tcp 0 0 10.0.0.3:24623 10.0.1.77:2181 TIME_WAIT root 0
发现user是root。于是以为是非Java应用,在不断地连接zookeeper。于是停止java程序,发现没有TIME_WAIT连接了。
但是确认是Java应用的问题,于是再重启Java应用,但没有再发现TIME_WAIT情况。很诡异。
问题不能重现了,相当的蛋疼。忽然想到线上的应用也许也有这个问题,于是到线下zookeeper服务器上查看了下,果然发现有同样的问题。
用tcpdump抓包和wireshark分析
先用tcpdump来查看下具体的网络连接,发现的确是连接连上再断开。于是先保存成cap文件,再用wireshark来分析:
- tcpdump -vv host 192.168.66.27 and port 2181 -w 2181.cap
但是也没有发现什么有用信息,的确是TCP连接连上,再FIN,ACK连接断开。
查看应用日志,发现Tomcat webcontext没有正常启动
没办法了,有两种考虑,一个是用strace,二是用btrace。但是btrace好久没用过了,不太想再去看例子文档。
还好,去下btrace之后,先去看了下应用的日志,发现应用报了一些ClassLoader的错误:
- Nov 24, 2014 7:32:43 PM org.apache.catalina.loader.WebappClassLoader loadClass
- INFO: Illegal access: this web application instance has been stopped already. Could not load org.apache.zookeeper.ClientCnxnSocketNIO. The eventual following stack trace is caused by an err
- or thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
- java.lang.IllegalStateException
- at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1564)
- at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1523)
- at ch.qos.logback.classic.spi.PackagingDataCalculator.loadClass(PackagingDataCalculator.java:198)
- at ch.qos.logback.classic.spi.PackagingDataCalculator.bestEffortLoadClass(PackagingDataCalculator.java:226)
- at ch.qos.logback.classic.spi.PackagingDataCalculator.computeBySTEP(PackagingDataCalculator.java:132)
- at ch.qos.logback.classic.spi.PackagingDataCalculator.populateUncommonFrames(PackagingDataCalculator.java:107)
- at ch.qos.logback.classic.spi.PackagingDataCalculator.populateFrames(PackagingDataCalculator.java:99)
因为有经验了,马上知道这个Tomcat因为其它原因webcontext实始化失败退出,然后后面的一些线程继续跑时,会抛出ClassLoader,或者Class not found的异常。
于是猜想到原因了:
Tomcat webcontext初始化失败,zookeeper的重连线程自动不断重连。
但是为什么重启Tomcat之后,没有重现TIME_WAIT的情况?
再折腾了下,发现只有当zookeeper重启后,应用才会出现大量的TIME_WAIT连接。报的是下面这个异常:
- 2014-11-24 19:42:44,399 [Thread-3-SendThread(192.168.90.147:4181)] WARN org.apache.zookeeper.ClientCnxn - Session 0x149c21809731325 for server 192.168.90.147/192.168.90.147:4181, unexpected error, closing socket connection and attempting reconnect
- java.lang.NoClassDefFoundError: org/apache/zookeeper/proto/SetWatches
- at org.apache.zookeeper.ClientCnxn$SendThread.primeConnection(ClientCnxn.java:867) ~[zookeeper-3.4.5.jar:3.4.5-1392090]
- at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:352) ~[zookeeper-3.4.5.jar:3.4.5-1392090]
这个异常的原因,是某些zookeeper的类没有加载到。
最终原因分析
梳理下整个流程:
- Tomcat启动,初始化webcontext;
- 初始化spring, spring初始某些些bean,这些bean包括了zookeeper的连接相关的bean;
- 这时zkClient(独立线程)已经连接上服务器了,但是classloader没有加载到org/apache/zookeeper/proto/SetWatches类;
- spring初始化失败,导致Tomcat webcontext初始化也失败,应用在挂起状态,但zkClient线程还是正常的;
- zookeeper服务器重启,zkClient开始重连,连接上zookeeper服务器;
- zkClient触发watch的一些代码,ClassLoader尝试加载org/apache/zookeeper/proto/SetWatches类,但是发现找不到类,于是抛出异常;
- zkClient捕获到异常,认为重连失败,close掉connection,休眠几秒之后,再次重连;
于是出现了zkClient反复重试连接zookeeper服务器,而且都是秒连秒断的情况。
总结:
这次排查花了不少时间,有个原因是开始没有去查看应用的日志,以为应用的是正常的,而且zookeeper.out的输出日志很多,也有一段时间了。
还有线上的应用比较坑爹,活动已经过期很久了,但是程序还是线上跑,也没有人管是否出问题了。
所以,主要精力放在各种网络连接状态的获取上。对去查看应用日志比较排斥。
还有一个原因是,问题比较诡异,有点难重现,当发现可以重现时,基本已经发现问题所在了。
排查问题还是要耐心收集信息,再分析判断。
zookeeper 大量连接断开重连原因排查的更多相关文章
- Android基于XMPP Smack Openfire下学习开发IM(五)连接断开重连
学习过程中大家都碰到过连接被断开的问题给困扰吧,下面教大家如何做到连接断开后,重新连接 首先要创建连接监听器,用来监听连接状态,这里我写了一个类 继承了ConnectionListener,重写了里面 ...
- openfire Android学习(五)------连接断开重连
首先要创建连接监听器,用来监听连接状态,这里我写了一个类 继承了ConnectionListener,重写了里面5个方法,最重要的两个方法connectionClosed()和connectionCl ...
- 再淡spring jdbc 连接池断开重连设置
先看一段错误日志: ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConne ...
- socket 如何判断远端服务器的连接状态?连接断开,需重连
fluent-logger-java is a Java library, to record events via Fluentd, from Java application. https://g ...
- Spring-Data-Redis 下实现jedis连接断开后自动重连
原先使用jedis的时候,处理手段是在从连接池获取连接时捕获JedisConnectionException异常,在异常处理部分重新获取连接,但是spring data redis似乎不会,如下所示: ...
- pymysql检查是否断开, 断开重连
python mysql使用持久链接 python链接mysql中没有长链接的概念,但我们可以利用mysql的ping机制,来实现长链接功能~ 思路: 1 python mysql 的cping 函数 ...
- dbcp重连问题排查
转载自:http://lc87624.iteye.com/blog/1734089 使用数据库连接池时,免不了会遇到断网.数据库挂掉等异常状况,当网络或数据库恢复时,若无法恢复连接池中的连接,那必然会 ...
- TCP socket如何判断连接断开
http://blog.csdn.net/zzhongcy/article/details/21992123 SO_KEEPALIVE是系统底层的机制,用于系统维护每一个tcp连接的. 心跳线程属于应 ...
- uni-app中websocket的使用 断开重连、心跳机制
前言 最近关于H5和APP的开发中使用到了webSocket,由于web/app有时候会出现网络不稳定或者服务端主动断开,这时候导致消息推送不了的情况,需要客户端进行重连.查阅资料后发现了一个心跳机制 ...
随机推荐
- or1200中载入存储类指令说明
下面内容摘自<步步惊芯--软核处理器内部设计分析>一书 OR1200中实现的载入存储类指令有8条,每条指令的作用与说明如表9.1所看到的. watermark/2/text/aHR0cDo ...
- Lua 字符串库函数总结
字符串库 注:字符串在Lua中是不可变的.不论什么的string操作都不会去改变原有的字符串.都是返回新的字符串 一.一般函数 1. 求长度 s = "Hello LUA "; p ...
- heap与stack的差
本文内容来源于<程序猿面试宝典>第三版. 在进行C/C++编程时.常常将操作的内存分下面几个类别: 栈区(stack):由编译器自己主动分配和释放,存放函数的參数值.局部变量的值等. 其操 ...
- 在linux下安装eclipse以及运行c++程序的安装步骤
1. 下载jre,eclipse,cdt 其中jre是java运行环境,eclipse需要先装jre,才可能运行,cdt是在eclipse中运行c\c++程序的插件. 下载jre 网址是: ...
- 【vue.js】绑定click事件
- 【laravel5.4+vue.js】laravel 循环三维数组,解决:htmlentities() expects parameter 1 to be string, array given
laravel循环三维数组 +++ vue.js循环三维数组 (数据均是以三维数组形式存在的) <form-item label="权限名称" prop=" ...
- hduoj----(1033)Edge
Edge Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ( ...
- 如何用python轻松破解wifi密码( 源码 )
摘要: 我得说明下这个东西一点都不高端,甚至看起来有点糟糕.而且用的是单线程~,因为过几天要搬家了,于是.. 环境准备 python2.7 凑合的linux 差不多的无线网卡 pywifi模块 弱口令 ...
- Android Fragment之间传递List数据
要说的是在两个Fragment之间传递List数据,比如有个List<User>,以及传递字符串数据,比如testId,该如何从FragmentA传递到FragmentB呢? 下面这个例子 ...
- Orm框架开发之NewExpression合并问题
之前都是看别人写博客,自己没有写博客的习惯.在工作的过程中,总是会碰到许多的技术问题.有很多时候想记录下来,后面一直有许多的问题等着解决.总想着等系统完成了,再回头总结下.往往结果就把这事抛到脑后了. ...