golang zk大量disconnected event_golang zk watch-程序员宅基地

技术标签: zookeeper  golang  Code  

背景

在容器平台上我们提供了zk做白名单功能,Pod启动时 sidecar会自动注册zk。昨天遇到zk server抖动,sidecar容器输出大量StateDisconnected事件,zk正常后仍无法恢复,由于大量日志造成sidecar容器 cpu占用过高,进而引发dockerdcpu占用过高,严重时影响dockerd正常调用。

问题分析

问题复现

正常情况下,sidecar启动后会去注册zk

# docker logs -f 01a1a4a74785
I0302 15:04:05.476463       1 manager.go:116] start run plugin zk
2021/03/02 15:04:05 Connected to 10.38.161.60:11000
I0302 15:04:05.488006       1 zk.go:152] zookeeper connect succeed: zk.srv:11000
2021/03/02 15:04:05 authenticated: id=33746806328105493, timeout=30000
2021/03/02 15:04:05 re-submitting `0` credentials after reconnect
I0302 15:04:05.516446       1 zk.go:220] watching zk node:[/tasks/cluster.xxx_default_deployment.htool/10.46.12.72] in cluster[xxx] #注册成功,开始watch

通过iptables来模拟异常,首先进入到容器network namesapce

pod=htool-6875bcb898-w7llc
containerid=$(docker ps |grep $pod|awk '{print $1}'|head -n 1)
pid=$(docker inspect -f {
     {
     .State.Pid}} $containerid)
nsenter -n --target $pid

使用iptables drop掉发往zk的请求(11000为zk server端口)

iptables -A OUTPUT -p tcp -m tcp --dport 11000 -j DROP

zk client自动重试(1s一次),日志显示Failed to connect to 10.38.161.54:11000: dial tcp 10.38.161.54:11000: i/o timeout

I0302 15:04:05.516446       1 zk.go:220] watching zk node:[/tasks/cluster.xxx_default_deployment.htool/10.46.12.72] in cluster[xxx]
2021/03/02 15:08:55 recv loop terminated: err=failed to read from connection: read tcp 10.46.12.72:36884->10.38.161.60:11000: i/o timeout
2021/03/02 15:08:55 send loop terminated: err=<nil>
2021/03/02 15:08:56 Failed to connect to 10.38.161.54:11000: dial tcp 10.38.161.54:11000: i/o timeout

网络恢复,删除iptables

iptables -D OUTPUT -p tcp -m tcp --dport 11000 -j DROP

出现大量StateDisconnected日志

I0302 15:09:50.951897       1 zk.go:232] Unknown zk event[StateDisconnected] for znode:[/tasks/cluster.xxx_default_deployment.htool/10.46.12.72]
I0302 15:09:50.951893       1 zk.go:232] Unknown zk event[StateDisconnected] for znode:[/tasks/cluster.xxx_default_deployment.htool/10.46.12.72]
...

问题分析

sidecar中zk watch代码如下:

exist, _, eventCh, err := conn.ExistsW(node) //监听zk事件
watcher:
        for {
                select {
                case e := <-eventCh:
                        switch e.State {
                        case zk.StateExpired:
                                return fmt.Errorf("node[%v] expired", node)
                        case zk.StateConnected, zk.StateHasSession:
                                return fmt.Errorf("Get zk event: %v ", e.State)
                        default:
                                klog.Infof("Get zk event[%v] for znode:[%v]", e.State, node) // 出错位置
                        }
                case <-ctx.Done():
                        // we close the conn in caller
                        break watcher
                }
        }

ExistsW函数由github.com/samuel/go-zookeeper/zk库提供,监听zk给定目录的事件

func (c *Conn) ExistsW(path string) (bool, *Stat, <-chan Event, error) {
    var ech <-chan Event
    ...
    ech = c.addWatcher(path, watchTypeData)
    return exists, &res.Stat, ech, err
}

当zk异常恢复后,c.addWatcher中的channelclose,即sidecareventCh关闭,进入死循环。

修复验证

知道了原因,修复很简单,判断下eventCh状态即可

    for {
        select {
        case e, ok := <-eventCh:
            if !ok {
                return fmt.Errorf("event channel closed")
            }
            if e.Err != nil {
                return fmt.Errorf("Get zk event: %v, err: %v", e.State, e.Err)
            }
            switch e.State {
            case zk.StateExpired:
                return fmt.Errorf("node[%v] expired", node)
            case zk.StateConnected, zk.StateHasSession:
                return fmt.Errorf("Get zk event: %v ", e.State)
            default:
                klog.Infof("Get zk event[%v] for znode:[%v]", e.State, node)
            }
        }

在修复代码后,再次验证可正常注册

2021/03/02 15:13:40 Failed to connect to 10.38.161.60:11000: dial tcp 10.38.161.60:11000: i/o timeout
2021/03/02 15:13:40 Connected to 10.38.161.55:11000
2021/03/02 15:13:40 authentication failed: zk: session has been expired by the server
W0302 15:13:40.222923       1 zk.go:300] meet error when watching node path: Get zk event: StateDisconnected, err: zk: session has been expired by the server
2021/03/02 15:13:40 Connected to 10.38.161.54:11000
2021/03/02 15:13:40 authenticated: id=177861994644216038, timeout=30000
2021/03/02 15:13:40 re-submitting `1` credentials after reconnect
I0302 15:13:41.238524       1 zk.go:220] watching zk node:[/tasks/cluster.xxx_default_deployment.htool/10.46.12.72] in cluster[xxx]

总结

这个问题其实与zk没关系,是由于没有判断channel状态,陷入死循环。通常情况下大部分应用只有退出时才会关闭channel,不需要特殊处理。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012986012/article/details/114290843

智能推荐

免费二级域名分发企业备案域名 阿里云备案域名_二级备案域名分发平台-程序员宅基地

文章浏览阅读7.3k次。幻影解析网(dns.52hyjs.com)专为新手站长提供的免费二级域名解析,域名均免费提供使用专门提供二级域名解析的平台,域名均免费提供使用,不收取任何费用,提供的域名当中有已备案域名和未备案域名,域名后缀多可自主选择解析全站提供免费阿里云企业备案域名 供大家使用https://dns.52hyjs.com/..._二级备案域名分发平台

nginx探索(7)nginx搭建负载均衡(centos7环境下)_两台centos7 做nginx负载均衡-程序员宅基地

文章浏览阅读235次。1.开三台服务器,第一台作为nginx负载均衡转发器,ip地址:192.168.241.198第二台作为web页面服务器(nginx)_两台centos7 做nginx负载均衡

saas平台架构分为哪几部分_saas架构介绍-程序员宅基地

文章浏览阅读3.1w次,点赞6次,收藏29次。saas平台架构需要完成从用户申请链接saas到用户对自己购买的功能模块的应用整个过程,用户用起saas看似简单快捷,但这个过程却需要saas平台架构默默完成的非常复杂的处理过程。通过对saas平台架构的了解,可以清晰的分化数据的处理过程,让用户也可以明白saas平台架构处理数据的优势。下面介绍:saas平台架构分为哪几部分。saas平台架构之呈现层saas平台架构的呈现层可以使用的客户端可能都浏..._saas架构介绍

jquery.form.js失效问题。-程序员宅基地

文章浏览阅读317次。项目中引用 jquery.form.js插件。打算用 .ajaxForm(options); 方式提交到后台,但是发现 .ajax 是可以正常交互的,但是 .ajaxform 就是不行。首先在form表单中,button的type问题。form表单中,button 的 type 有三种值。分别是:reset : 如..._引入的jquery.form.js不生效

SI5338 时钟芯片驱动-程序员宅基地

文章浏览阅读5.2k次,点赞4次,收藏12次。该时钟芯片可以做到任意频率的时钟输出控制接口为IIC接口,主要的资料为 :AN428.pdfSi5338-RM.pdfSi5338芯片手册我们首先应该芯片手册,然后对应寄存器说明为Si5338-RM.pdf,AN428里给了一个单片机的demo此外由于寄存器比较多,我们可以借助官方提供的工具软件设置好参数通过export可获取对应的寄存器的值下面是大概的IIC时序代码:/*Si5338.cCreated on: 2020年9月13日 Author: Administr._si5338

【资源集合/国产】狐妖小红娘动画+漫画[带P站精选红红图]_黄色动图-程序员宅基地

文章浏览阅读10w+次,点赞5次,收藏14次。_(:з」∠)_都是每话保存的,第一次这样保存一部漫画,真花费数个小时才完成,需要的就下载=-=-=-=-=-=-==-==-=-=-=-=-=-==-==-=-=-=-=-=-==-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=[190611]狐妖小红娘漫画[1-337][797MB]下载地址:https://waecy2.pipipan.com/f..._黄色动图

随便推点

Java多线程-生产者消费者模式_多线程生产者生产一个汉堡-程序员宅基地

文章浏览阅读395次。简单的生产者消费者模式_多线程生产者生产一个汉堡

ES6 关于var,let, const的作用域考题-程序员宅基地

文章浏览阅读203次。ES6 关于var,let, const的作用域考题

关于C++中用静态成员统计实例化对象个数问题_CVTE技术面问题_static成员自动统计-程序员宅基地

文章浏览阅读2.2k次,点赞3次,收藏4次。17年3月25号去了广州的CVTE技术面.面试官问到如何去统计一个类的实例化对象个数,这里想了一下可以用一个static数据成员去统计,但是这里注意必须在类的外部定义和初始化每个静态成。 不过我们可以为静态成员提供const整数类型的类内初始值,这样子的话要求静态成员必须是字面值常量类型的 constexpr。 下面给出自己的实现。#include using names_static成员自动统计

如何在浏览器中添加Metamask_meta mask添加网页-程序员宅基地

文章浏览阅读3.5k次。Chrome应用商店https://chrome.google.com/webstore/category/extensions?hl=zh-CN一般需要FQ和谐上网一下。搜索Metamask,那只小狐狸就是Metamask咯。点击小狐狸之后,再点击“添加至Chrome”即可。_meta mask添加网页

python3.7怎么安装jupyter_anaconda3安装及jupyter环境配置全教程-程序员宅基地

文章浏览阅读513次。anaconda3安装及jupyter环境配置全教程,环境,用户组,用户,可以使用,配置文件anaconda3安装及jupyter环境配置全教程易采站长站,站长之家为您整理了anaconda3安装及jupyter环境配置全教程的相关内容。1. 下载可以去清华源下载最新版的anaconda包,这比在官方网站下载快得多,地址如下:https://mirrors.tuna.tsinghua.edu.cn..._python安装jupyter anconda 3.7.0

已解决Could not fetch URL https://pypi.tuna.tsinghua.edu.cn/simple/pip/: There was a problem confirming-程序员宅基地

文章浏览阅读2.6w次,点赞30次,收藏72次。已解决(pip升级报错)WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simpleRequirement already satisfied: pip in e:\anaconda\install_root\lib\_could not fetch url

推荐文章

热门文章

相关标签