表象:zookeeper因内存使用率导致的集群不可用

线上Zookeeper集群出现告警,节点内存100%占用,日志因配置问题无法查看。网络、TCP连接、磁盘IO、线程数均正常。节点启动后,CPU利用率约30%,内存仍升高,分析发现大量TIME_WAIT连接。调整内存配置后问题缓解。进一步调查发现6个节点中的11个Docker不可用,调整为最新5个节点后集群恢复。问题遗留:节点启动时内存为何快速增加。推测可能与数据同步和大量TCP尝试连接有关。
摘要由CSDN通过智能技术生成

         线上突然告警,zk集群不可用。随机看了zk节点挂了前的的机器的CPU与内存,内存100%,如下图所示。

         首先我看了日志,由于线上配置的问题,所有的日志全部扔掉了。基于日志没有发现有价值的内容,接着又看了节点的网络,TCP连接数,磁盘IO,线程数,这些都是在正常范围内。    

        接着想着尝试启动一个节点,启动成功。但是通过top命令查看zk线程CPU利用率在30%左右,在正常情况下zk一般不耗内存(除非异常了)。

下面是最耗CPU的堆栈信息:

"NIOServerCxn.Factory:0.0.0.0/0.0.0.0:22288" daemon prio=10 tid=0x00007ff25c22e000 nid=0x9b24b runnable [0x00007ff17dab6000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
    at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:210)
    at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:65)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:69)
    - locked <0x0000000601b704e8> (a sun.nio.ch.Util$2)
    - locked <0x0000000601b71370> (a java.util.Collections$UnmodifiableSet)
    - locked <0x0000000601b70de8> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)
    at org.apache.zookeeper.server.NIOServerCnxnFactory.run(NIOServerCnxnFactory.java:178)
    at java.lang.Thread.run(Thread.java:662)

通过netstat命令查看连接状态,发现有许多TIME_WAIT

[root@host-x-x-x-x bin]# netstat -pano | grep 22288
tcp        0      0 ::ffff:127.0.0.1:15298      ::ffff:127.0.0.1:22288      TIME_WAIT   -                   timewait (15.34/0/0)
tcp        0      0 ::ffff:x.x.x.x:22288    ::ffff:x.x.x.x:39904  TIME_WAIT   -                   timewait (30.02/0/0)

查看zk的启动状态,结果如下(当然,集群要全部启动后才能看到是master/follower):

        当然过了几分钟,该节点也挂了。只好继续查找原因,当节点启动后,虽然集群不可用,但是还是在尝试建立TCP连接,至于为啥是TCP四次挥手中的TIME_WAIT状态,我猜测是由于在zk集群节点挂后,我马上建立重启,但集群未生效,节点通过TIME_WAIT允许老的重复分节在网络中消逝 (端口号还是保持不变)。

         该节点启动不一会儿(有正常的端口号),端口又挂了。查看内存,发现内存使用率陡增(集群不可用,为啥内存还陡增了?虽然zk集群不可用,但是客户端与该ip在尝试建立socket连接,不断分配端口文件描述符……期望有更好的理由[吃瓜])。首先想到的是调整内存。

确实调整内存后很有效果 ,不再出现内存陡增情况。

    接着继续看zk配置的节点列表,总共有11个docker,但有6个docker不可用。这就很明显了,过半的节点不可用,当然集群不可用了。因此将server保留最新的5个节点,启动zk节点,集群可用。

        虽然问题解决了,但遗留了一个问题:在集群不可用时,启动其中一个zk节点,为啥短时间内内存使用率很高? 

         没有请求到zk,不代表tcp请求没建立。这套zk客户端ip很多,虽然请求被拒絕了,但是还是在试着建立socket连接,尝试进行TCP连接,这也将消耗大量的资源(但还是不足以说明内存使用率过高)

       后续思考了一下,由于节点启动后,会进行数据同步操作,对内存的消耗很大。由于数据量很大,节点启动后进行数据同步,对内存的消耗很大,而zk配置的是默认的内存,可能会不断的对内存进行重新分配,导致堆内存接近docker内存,如下图,实际docker的最大内存为8G 。继续进行数据恢复则会导致内存溢出。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值