转自: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,滚动日志一天就被冲掉了,这个不科学。

再仔细查看下日志里的内容,发现有很多连接建立好,马上又断开:

  1. 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)
  2. 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
  3. 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
  4. EndOfStreamException: Unable to read additional data from client sessionid 0x0, likely client has closed socket
  5. at org.apache.zookeeper.server.NIOServerCnxn.doIO(NIOServerCnxn.java:220)
  6. at org.apache.zookeeper.server.NIOServerCnxnFactory.run(NIOServerCnxnFactory.java:208)
  7. at java.lang.Thread.run(Thread.java:745)
  8. 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的服务器上查看连接的状态:

  1. netstat -antp | grep 2181

发现有很多TIME_WAIT状态的连接:

  1. tcp        0      0 10.0.0.3:44269         10.0.1.77:2181         TIME_WAIT   -
  2. tcp        0      0 10.0.0.3:43646         10.0.1.77:2181         TIME_WAIT   -
  3. tcp        0      0 10.0.0.3:44184         10.0.1.77:2181         TIME_WAIT   -
  4. tcp        0      0 10.0.0.3:44026         10.0.1.77:2181         TIME_WAIT   -
  5. 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 输出了一些信息:

  1. tcp        0      0 10.0.0.3:41772     10.0.1.77:eforward     TIME_WAIT   root       0
  2. tcp        0      0 10.0.0.3:41412     10.0.1.77:eforward     TIME_WAIT   root       0
  3. tcp        0      0 10.0.0.3:24226     10.0.1.77:2181         TIME_WAIT   root       0
  4. 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来分析:

  1. tcpdump -vv host 192.168.66.27 and port 2181 -w 2181.cap

但是也没有发现什么有用信息,的确是TCP连接连上,再FIN,ACK连接断开。

查看应用日志,发现Tomcat webcontext没有正常启动

没办法了,有两种考虑,一个是用strace,二是用btrace。但是btrace好久没用过了,不太想再去看例子文档。

还好,去下btrace之后,先去看了下应用的日志,发现应用报了一些ClassLoader的错误:

  1. Nov 24, 2014 7:32:43 PM org.apache.catalina.loader.WebappClassLoader loadClass
  2. 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
  3. or thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
  4. java.lang.IllegalStateException
  5. at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1564)
  6. at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1523)
  7. at ch.qos.logback.classic.spi.PackagingDataCalculator.loadClass(PackagingDataCalculator.java:198)
  8. at ch.qos.logback.classic.spi.PackagingDataCalculator.bestEffortLoadClass(PackagingDataCalculator.java:226)
  9. at ch.qos.logback.classic.spi.PackagingDataCalculator.computeBySTEP(PackagingDataCalculator.java:132)
  10. at ch.qos.logback.classic.spi.PackagingDataCalculator.populateUncommonFrames(PackagingDataCalculator.java:107)
  11. 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连接。报的是下面这个异常:

  1. 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
  2. java.lang.NoClassDefFoundError: org/apache/zookeeper/proto/SetWatches
  3. at org.apache.zookeeper.ClientCnxn$SendThread.primeConnection(ClientCnxn.java:867) ~[zookeeper-3.4.5.jar:3.4.5-1392090]
  4. at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:352) ~[zookeeper-3.4.5.jar:3.4.5-1392090]

这个异常的原因,是某些zookeeper的类没有加载到。

最终原因分析

梳理下整个流程:

  1. Tomcat启动,初始化webcontext;
  2. 初始化spring, spring初始某些些bean,这些bean包括了zookeeper的连接相关的bean;
  3. 这时zkClient(独立线程)已经连接上服务器了,但是classloader没有加载到org/apache/zookeeper/proto/SetWatches类;
  4. spring初始化失败,导致Tomcat webcontext初始化也失败,应用在挂起状态,但zkClient线程还是正常的;
  5. zookeeper服务器重启,zkClient开始重连,连接上zookeeper服务器;
  6. zkClient触发watch的一些代码,ClassLoader尝试加载org/apache/zookeeper/proto/SetWatches类,但是发现找不到类,于是抛出异常;
  7. zkClient捕获到异常,认为重连失败,close掉connection,休眠几秒之后,再次重连;

于是出现了zkClient反复重试连接zookeeper服务器,而且都是秒连秒断的情况。

总结:

这次排查花了不少时间,有个原因是开始没有去查看应用的日志,以为应用的是正常的,而且zookeeper.out的输出日志很多,也有一段时间了。

还有线上的应用比较坑爹,活动已经过期很久了,但是程序还是线上跑,也没有人管是否出问题了。

所以,主要精力放在各种网络连接状态的获取上。对去查看应用日志比较排斥。

还有一个原因是,问题比较诡异,有点难重现,当发现可以重现时,基本已经发现问题所在了。

排查问题还是要耐心收集信息,再分析判断。

zookeeper 大量连接断开重连原因排查的更多相关文章

  1. Android基于XMPP Smack Openfire下学习开发IM(五)连接断开重连

    学习过程中大家都碰到过连接被断开的问题给困扰吧,下面教大家如何做到连接断开后,重新连接 首先要创建连接监听器,用来监听连接状态,这里我写了一个类 继承了ConnectionListener,重写了里面 ...

  2. openfire Android学习(五)------连接断开重连

    首先要创建连接监听器,用来监听连接状态,这里我写了一个类 继承了ConnectionListener,重写了里面5个方法,最重要的两个方法connectionClosed()和connectionCl ...

  3. 再淡spring jdbc 连接池断开重连设置

    先看一段错误日志: ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConne ...

  4. socket 如何判断远端服务器的连接状态?连接断开,需重连

    fluent-logger-java is a Java library, to record events via Fluentd, from Java application. https://g ...

  5. Spring-Data-Redis 下实现jedis连接断开后自动重连

    原先使用jedis的时候,处理手段是在从连接池获取连接时捕获JedisConnectionException异常,在异常处理部分重新获取连接,但是spring data redis似乎不会,如下所示: ...

  6. pymysql检查是否断开, 断开重连

    python mysql使用持久链接 python链接mysql中没有长链接的概念,但我们可以利用mysql的ping机制,来实现长链接功能~ 思路: 1 python mysql 的cping 函数 ...

  7. dbcp重连问题排查

    转载自:http://lc87624.iteye.com/blog/1734089 使用数据库连接池时,免不了会遇到断网.数据库挂掉等异常状况,当网络或数据库恢复时,若无法恢复连接池中的连接,那必然会 ...

  8. TCP socket如何判断连接断开

    http://blog.csdn.net/zzhongcy/article/details/21992123 SO_KEEPALIVE是系统底层的机制,用于系统维护每一个tcp连接的. 心跳线程属于应 ...

  9. uni-app中websocket的使用 断开重连、心跳机制

    前言 最近关于H5和APP的开发中使用到了webSocket,由于web/app有时候会出现网络不稳定或者服务端主动断开,这时候导致消息推送不了的情况,需要客户端进行重连.查阅资料后发现了一个心跳机制 ...

随机推荐

  1. 批处理文件:将目录下所有的jar文件都加到CLASSPATH

    简便写法如下: 代码 : @echo off SetLocal EnableDelayedExpansion FOR %%i IN ("XXX\lib\*.jar") DO SET ...

  2. Apache Hadoop 3.0新版本介绍及未来发展方向

    过去十年,Apache Hadoop从无到有,从理论概念演变到如今支撑起若干全球最大的生产集群.接下来的十年,Hadoop将继续壮大,并发展支撑新一轮的更大规模.高效和稳定的集群. 我们此次将向大家全 ...

  3. cocos2dx 3.2 解决输入框(TextField,TextFieldTTF) 中文乱码问题

    近期开发cocos2dx 项目,做一个小游戏.(个人喜欢用最新版本号) 没系统学习就是问题多多,遇到了非常多问题,比方全部的opengl api都必须在主线程中调用, 这让我在多线程载入方面吃了不少亏 ...

  4. HDUOJ---携程员工运动会场地问题

    携程员工运动会场地问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. HDUOJ-----Be the Winner

    此题用到的概念: [定义1]:若一堆中仅有一个石子,则被称为孤单堆.若大于1个,则称为充裕堆. [定义2]:T态中,若充裕堆的堆数大于等于2,则称为完全利他态,用T2表示:若充裕堆的堆数等于0,则称为 ...

  6. Outlook如何定时发邮件

    http://jingyan.baidu.com/article/c843ea0b63e15377931e4a0e.html 更多文章: Outlook定时发送邮件问题-http://blog.sin ...

  7. PowerDesigner 12小技巧-pd小技巧-pd工具栏不见了-pd修改外键命名规则-pd添加外键

    PowerDesigner 12小技巧-pd小技巧-pd工具栏不见了-pd修改外键命名规则-pd添加外键 1. 附加:工具栏不见了 调色板(Palette)快捷工具栏不见了PowerDesigner ...

  8. 重写lucene.net的分词器支持3.0.3.0版本

    lucene.net中每个分词器都是一个类,同时有一个辅助类,这个辅助类完成分词的大部分逻辑.分词类以Analyzer结尾,辅助类通常以Tokenizer结尾.分类词全部继承自Analyzer类,辅助 ...

  9. lsnrctl: error while loading shared libraries: /opt/app/oracle/product/11.2/db_1/lib/libclntsh.so.11

    错误描述: 安装好数据库后,在oralce用户下敲入 查看监听状态命令,返回错误提示 [oracle@centos3 ~]$ lsnrctl statuslsnrctl: error while lo ...

  10. 转 web前端性能分析--分析篇

    通过具体实施后就可以获得第一手的web前端性能的数据了,然后每次新版本都跑,这就会获得大量的数据,为性能分析提供了基础的输入,同时应该还要综合使用多种工具去从不同的方向收集数据:比如showslow同 ...