zookeeperOOM问题排查
背景
最近折腾的数据库同步项⽬中,⼤量使⽤了zookeeper(版本3.3.3),可以说是强依赖,但是最近频频出现zookeeper内存使⽤率达到100%,⽽且是GC不掉,直接导致整个系统挂起,伤不起阿shoofly
分析
因为⼤部分的情况都是⽆法GC回收,所以很⼤程度上怀疑出现memory leak。
设置了jvm参数,收集了⼀下OOM导致jvm crash之后的⽇志⽂件进⾏分析
1.-XX:+HeapDumpOnOutOfMemoryError
leak分析:
从leak分析来看,⽐较明显,99%的内存都被Leader类的obrvingLearners给吃光了,所以重点就可以落在zookeeper obrver的使⽤上了。
zookeeper的obrver模式
主要⽤于解决读扩展性的问题,obrver的节点不参与vote,也就是说写操作都只会发⽣在leader/follower中进⾏投票决策,⽽obrver就是⼀个只读镜像。
special怎么读
但有⼀点和数据库的master/slave模式不同的是,obrver也会接受写请求,但会将请求转交给leader/follower集群进⾏处理,并同步等待返回结果。
可以说obrver⽐较巧妙的解决了读扩展性的问题,在zookeeper3.4.5版本,增加了readonlymode,和obrver模式还是有所不同。在我之前的⽂章中,,有描述在项⽬中使⽤obrver的情况:
从图中可以看出:
1. 整个zookeeper⼤集群有2部分组成,杭州的⼀个leader/follower集群 + 美国的⼀个obrver集群
2. 为保证可⽤性,杭州集群的机器分别部署在3个机房中,(满⾜任意机房AB, 机房A+机房B > 机房A+机房B+机房C/2),最⼩的部署结构为3+2+2机器,这样可以确保,任何⼀个机房挂了,都可以保证整个zookeeper集群的可⽤性
代码分析:burnout
看完issue后,这时候问题已经明显了。
在Leader.java类中:
1./**
2. * Remove the learner from the learner list
3. *
4. * @param peer
5. */
什么是pop
6. void removeLearnerHandler(LearnerHandler peer) {
人人听力网7. synchronized (forwardingFollowers) {
8. ve(peer);
9. }it学校
10. synchronized (learners) {
11. ve(peer);
12. }
13. }
这⾥⾯Leader节点,在与对应的follower/obrver之间的链接异常断开时,会清理当前内存中的引⽤句柄 (不然下次的vote信息还会发送到挂了的节点上)。
⽽leader在往obrver上推送write数据,会遍历当前内存中的obrvingLearners列表
1./**
2. * nd a packet to all obrvers
galvanized steel3. */
4. void ndObrverPacket(QuorumPacket qp) {
5. synchronized(obrvingLearners) {
6. for (LearnerHandler f : obrvingLearners) {
7. f.queuePacket(qp);
8. }
9. }
10. }
再看⼀下LearnerHandler.java类中:
1.public class LearnerHandler extends Thread {新概念英语视频
idea
2.
3.public void run() {
4. p = queuedPackets.poll();
5. ........
6.}
7.void queuePacket(QuorumPacket p) {
8. queuedPackets.add(p);
六级多少分算过关9. }
10.
11.}
LearnerHandler中的处理⽅式是⼀种典型的异步处理,通过queuedPackets接受任务数据,然后线程
异步进⾏消费处理。 因为obrver 可能因为⽹络抖动,会断开与Leader之间的链接,就会触发shutdown⽅法。⽽shutdown⽅法就是尝试将⾃⼰从Leader的obrver句柄中移除
所以整个问题原因已经⽐较明确,removeLearnerHandler没有清理obrver队列中的句柄,导致⼀直进⾏queuePacket调⽤,⼜没有异步线程进⾏消费,所以暴内存是迟早的事。
总结
特别注意:3.3.6中居然没修复这个问题,所以可升级zookeeper⾄3.4.5, 经过实际验证⼤家可放⼼升级(我的client 3.3.6 , rver 3.4.5)