问题现象
最后发现线上的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的输出日志很多,也有一段时间了。
还有线上的应用比较坑爹,活动已经过期很久了,但是程序还是线上跑,也没有人管是否出问题了。
所以,主要精力放在各种网络连接状态的获取上。对去查看应用日志比较排斥。
还有一个原因是,问题比较诡异,有点难重现,当发现可以重现时,基本已经发现问题所在了。
排查问题还是要耐心收集信息,再分析判断。
相关推荐
1. **连接与断开**:ZkTools允许用户通过简单的命令行接口连接到Zookeeper服务器,同时也可以快速断开连接。 2. **节点操作**:可以创建、删除、列出、修改Zookeeper中的节点,包括递归操作,便于管理复杂的节点...
会话是客户端与 Zookeeper 服务器之间的一次交互过程,如果服务器与客户端的连接断开,临时节点将被自动删除。Watcher 是一种事件监听机制,可以注册在 Znode 上,当 Znode 发生变化时,Watcher 将接收到通知。 在 ...
节点分为临时节点和持久节点,临时节点在客户端断开连接后会自动删除。 8. **Watch机制**:Watch是Zookeeper的一种事件监听机制,客户端可以为任何节点设置Watch,当该节点发生变化时,Zookeeper会向设置Watch的...
临时节点在客户端断开连接时自动删除,而顺序节点则可以用于实现公平的锁策略。 5. **集群管理**: - ZooKeeper 可以作为集群的元数据中心,存储集群状态信息,例如节点状态、任务分配等。 - 它提供了集群领导者...
Znodes分为临时节点和持久节点,临时节点在创建它的客户端断开连接后自动删除,而持久节点则一直存在,直到被显式删除。 4. **Zookeeper的协议和机制**: - **原子广播协议**:Zookeeper的更新操作是原子的,所有...
4.1 日志分析:通过日志文件定位问题,如连接断开、数据同步失败等。 4.2 心跳检测:监控Zookeeper节点的心跳,及时发现并处理异常。 4.3 数据恢复:通过备份或数据迁移,恢复丢失的数据或服务。 五、安全性 5.1 ...
后者在创建它的客户端断开连接时自动删除。 3. **Watcher机制**: - Watcher是Zookeeper的一个重要特性,它允许客户端注册监听ZNode的改变(如数据更改、节点创建或删除)并接收通知。 - Watcher是一次性的,当...
- **监控与日志**:监控 Zookeeper 的运行状态,包括节点状态、会话、操作日志等,对于故障排查和性能优化至关重要。 - **性能调优**:调整 Zookeeper 集群的大小、网络设置、内存分配等参数,以应对高并发和大...
临时节点在创建它的客户端断开连接时自动删除。 - **监视(Watch)**: 客户端可以设置监视点来监听Znode的变化,一旦发生改变,Zookeeper会向客户端发送事件通知。 2. **Zookeeper查看器功能** - **节点浏览**: ...
- ZNode 分为临时节点和持久节点,临时节点在创建它的客户端断开连接后自动删除。 3. **API 接口**: - ZooKeeper 提供了丰富的 Java API,包括创建、读取、更新、删除 ZNode,以及监控节点变化等操作。 - `...
1. Zookeeper节点(Znode):Zookeeper的数据存储结构是树形的,每个节点称为Znode,分为临时节点和永久节点,临时节点在客户端断开连接后会自动删除,而永久节点则不会。 2. 原子操作:所有对Zookeeper的操作都是...
如果服务器端或客户端断开连接,临时节点将被删除。 3. **Watcher**: Watcher是一种事件监听机制,当节点状态发生改变时,已注册的Watcher会接收到通知,实现快速响应和处理。 **ZooInspector功能解析** 1. **...
2. 客户端连接问题:排查网络问题,确保客户端与ZooKeeper服务之间的连通性。 3. 性能瓶颈:分析系统资源使用情况,优化配置,如增加内存、调整网络带宽等。 总结,Hadoop ZooKeeper 3.4.10在Linux环境中的应用涉及...
- **持久化和临时节点**:`-e`参数创建临时节点,会随着客户端断开连接而消失;默认创建的是持久节点。 - **顺序节点**:`-s`参数创建顺序节点,节点名后会附加一个自增的序列号。 4. **Zookeeper的应用场景** -...
Znode 分为临时节点和永久节点,临时节点在客户端断开连接后会被自动删除,而永久节点则不会。 2. **Watch 机制**: Zookeeper 提供了一种观察机制,即 Watcher,客户端可以在特定 Znode 上设置 Watcher,当该 Znode...
此外,ZooKeeper的会话管理也很关键,如果客户端会话超时或断开,未正确处理会话恢复的代码可能会出现问题。 为了调试和修复这些问题,我们需要深入理解ZooKeeper的API文档,了解每个方法的使用条件和返回值,同时...
节点分为临时节点和持久节点,临时节点在创建它的客户端断开连接后会被自动删除。 4. **会话与心跳机制**:Zookeeper客户端与服务器之间通过会话(Session)保持连接,会话期间服务器通过心跳机制监控客户端状态,...
超时机制确保了临时节点在客户端断开连接后能够被正确清理。 12. ZooKeeper的应用场景 Zookeeper常用于实现分布式配置管理、分布式命名服务、分布式锁、分布式队列等。例如,它可以用来管理分布式应用的配置信息,...
ZNode分为临时节点和永久节点,临时节点在创建它的客户端断开连接后自动删除,而永久节点则一直存在,直到被显式删除。此外,ZNode还支持watch机制,可以监听节点的变化,实时触发通知。 ZooKeeper的协议和算法也是...
3. **会话(Session)**: 客户端与Zookeeper服务器之间的连接称为会话,会话期间,Zookeeper保证至少一次的消息传递。如果会话超时或网络断开,客户端需要重新建立会话。 4. **一致性保证**: Zookeeper提供强一致性...