ZookeeperNet太难用,写了个RetryHelper来进行配套使用

普通的zk用法,如下写法:

zk.Exists("/aaa", true);
zk.Create(...);

但是由于这些API会抛Zookeeper的Exception,比如ConnectionLossException, NoNodeException等,所以必须配合一堆try/catch的机制来catch错误,catch后再处理...

写起来很麻烦

因此写了个RetryHelper来封装上面这个try/catch行为,用起来也比较方便,如下:

RetryHelper helper=RetryHelper.Make();

helper.CreateNodeStructure = () => { Console.WriteLine("CreateNodeStructure"); };
helper.FixConnectionLossAction = () => { Console.WriteLine("FixConnectionLossAction");};
helper.IfErrorThen = () => { Console.WriteLine("IfErrorThen"); };
helper.Execute(() =>
{
     this.zk.GetChildren(...);
});

上面的意思是如果在Execute中,如果报错了,则会看报错的是哪种类型,如果是ConnectionLoss则执行FixConnectionLossAction委托,如果是NoNode则执行建立节点的委托

也就是将最常见的2个zookeeper动作给结构化了:建立节点目录结构以及连接丢失时的重新连接动作

RetryHelper代码:

public class RetryHelper
    {
        private int retryDelay = 500;
        private long signal = 0;
        public Action IfErrorThen;
        public Action CreateNodeStructure;
        public Action FixConnectionLossAction;

        public static RetryHelper Make()
        {
            return new RetryHelper();
        }

        public void Execute(Action action)
        {
            while (true)
            {
                try
                {
                    action();
                    break;
                }
                catch (ZooKeeperNet.KeeperException.NoNodeException ex)
                {
                    //create node structure

                    Console.WriteLine("retry helper NoNodeException: " + ex.Message);

                    if (CreateNodeStructure != null)
                        RetryHelper.Make().Execute(CreateNodeStructure);
                    continue;
                }
                catch (ZooKeeperNet.KeeperException.ConnectionLossException ex)
                {
                    Console.WriteLine("retry helper ConnectionLossException: " + ex.Message);

                    long attempSignal = Interlocked.Read(ref signal);

                    while (Interlocked.Read(ref signal) > 0)
                        Thread.Sleep(retryDelay);

                    if (attempSignal == 0)
                    {
                        Interlocked.Increment(ref signal);

                        if (FixConnectionLossAction != null)
                            RetryHelper.Make().Execute(FixConnectionLossAction);

                        Interlocked.Decrement(ref signal);
                    }

                    continue;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("retry helper catch: " + ex.Message);
                    Thread.Sleep(retryDelay);

                    if (IfErrorThen != null)
                        IfErrorThen();
                    continue;
                }
            }
        }
    }

仔细看上面代码的朋友肯定也注意到里面catch connectionloss exception的代码块中使用了Interlocked,这是因为:在多线程系统侠,如果zk连接丢失了,由于多个地方都在尝试zk操作,所以会导致并发性的进入catch loss connection exception代码处理块,如果此时不加判断的处理所有并发请求,则会出现连接多次到zk,严重影响性能;因此,这里的代码实际上意图是将多次连接请求合并为一次连接。此处特别感谢我同事的code review,哈哈。

下面是个测试并发消除的demo,为了让结果清晰,我把RetryHelper的catch中的Console.WriteLine注释了

static void Main(string[] args)
        {
            RetryHelper helper=RetryHelper.Make();

            helper.CreateNodeStructure = () => { Console.WriteLine("CreateNodeStructure"); };
            helper.FixConnectionLossAction = () =>
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId+" FixConnectionLossAction BEGIN "+DateTime.Now.ToString());
                Thread.Sleep(2000);
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " FixConnectionLossAction END " + DateTime.Now.ToString());
            };
            helper.IfErrorThen = () => { Console.WriteLine("IfErrorThen"); };

            var tasks=new List<Task>();
            for (int i = 0; i < 10; i++)
            {
                var task = new Task(() => {
                    helper.Execute(() =>
                    {
                        throw new ZooKeeperNet.KeeperException.ConnectionLossException();
                    });
                });
                tasks.Add(task);
            }

            tasks.ForEach(t=>t.Start());

            Task.WaitAll(tasks.ToArray());

            Console.ReadKey();
        }

运行:

code download

ZookeeperNet太难用,写了个RetryHelper来进行配套使用,布布扣,bubuko.com

时间: 2024-10-13 21:59:59

ZookeeperNet太难用,写了个RetryHelper来进行配套使用的相关文章

ZookeeperNet太难用,写了个RetryHelper来进行配套使用 - McKay - 博客园

ZookeeperNet太难用,写了个RetryHelper来进行配套使用 - McKay - 博客园 ZookeeperNet太难用,写了个RetryHelper来进行配套使用

Oops,OOP太难玩了

花了好几天一边玩游戏一边折腾重构,就为了给方块的移动加上动画. 失败了嗯. 首先想到的是让Block类继承View,然后让方块绘画自己,自己执行动画. 因为之前是直接往SurfaceView上画正方形的,所以肯定加不上动画. 但是后来发现这样就用不着SurfaceView了,于是重新写了布局,想着把方块扔到容器里. 结构特别清晰易懂是不是! 简直太赞了,跟个逼真的似的,我脑子里就出现了往RelativeLayout里面一个个填入方块,然后消除了之后方块掉落的场景. 方块不再只是个正方形了,它拥有

不懂网络营销?HTML,Javascript,语言太难?做网络运营营销,你必须掌握的能力

在如今的互联网时代,有一个岗位是基本每家企业人事部都会常常挂在嘴边的,网络营销人才,老板一直在招聘好的网络营销人才,因为他知道网络营销是每家企业都在争夺的命脉. 网络营销人才就是简单的互联网+营销.现在只懂互联网不懂营销,只懂营销又不懂互联网的人,注定会慢慢的被时间埋葬在互联网的长河中.因此现在很多企业都在找互联网人才,一些互联网的专业技能是做互联网运营的人,必须要掌握的.今天高级网络运营营销师王剑超,就给大家讲讲我们作为互联网人员应该重视的那些是必备的专业技能. 一.多角度扩展视野 做互联网的

华为招程序员的面试题:8+11=?,网友:真的太难了

前言:一个好的程序员需要相当程度的逻辑思维能力,要成为一个优秀的程序员,逻辑思维能力是关键,写程序也是对该能力的一种锻炼. 最近得程学院社区上传播着这样一个帖子:一名程序员面试华为,面试官出了这样一个面试题,网友:题目太难了.这是怎么回事呢?这是一道怎样的面试题呢? 该员工说自己上次去华为面试,其中有个面试官给自己出了一道算术题,题目是这样的:第一行是1+4=5:第二行是2+5=12:第三行是3+6=21:最后要求算出第4行8+11等于多少? 这位员工说自己算了很久还是算错了,也因此被淘汰了,于

2019年互联网寒冬,企业大裁员,我们太难了

2019年,我们真的是太难了,大家又没感觉到? “上午还在写代码修Bug,下午就被裁掉了……” 随着寒冬的到来,各大互联网公司裁员的消息屡见不鲜.甚至连一些科技巨头都在人力优化和收紧,下面是今年大公司裁员的详情,图片来源于网络. 再看看网络上的其他信息. 新浪微博的裁员: Keep裁员信息: 2019年,资本寒冬笼罩之下,各行业裁员消息频出,尤以互联网行业首当其冲.红利已过,大势已去,唱衰之声日隆,职场更是哀鸿一片,遍地爆雷,裁员风波一浪高过一浪,500强名企皆不得幸免. 由于整个市场经济的下行

ejs跟angularjs相比,实在是太难写了,附实例!

例如一段以下代码的实现 判断 ejs <% if (data.success) { %> <span><%= data.success %></span> <% } %> <% if (data.err) { %> <span><%= data.err %></span> <% } %> angularjs <span>{{ data.success }}</span&

慢慢产品经理路,第一步真是太难了。

11月1日,正式迈入产品经理这行. 听起来高大上,其实是个苦逼无比的工作."经理",呵呵.目前来说就是个总管,啥都要管,鸡毛蒜皮的事,只要和产品有关,就是你的事儿. 过去4年,做网站运营,而且也做出了一定的成绩,当上了主管,人生中第一份工作,个人觉得做到这样样的成绩,还是挺好的.薪资不错,虽然销售压力大,但是因为已经有一定的规模了,也还好.最后辞职的原因,是因为公司比较小,而且私企,老板,你们都懂的,出于未来职业规划考虑,辞职了.哈哈,结果在辞职以后,就出去旅游浪了一个月.于是..就懒

跳槽意愿报告:跳槽不太难,钱是原动力

如今的职场人更趋务实--通过跳槽实现自身职场利益的最大化.为助跳槽大军们一臂之力,前程无忧(www.51job.com)特此在"金三银四"跳槽好时节推出此本跳槽意愿调查报告,期望能给求职者们作个参考,进一步接近自己的职场梦想. 跳槽意愿度:上海最受青睐,求职者仍钟爱外企 目标城市:上有天堂,下有沪穗 据前程无忧最新出炉的"2015年第一季度求职者跳槽意愿度调查"结果显示,上海以显著的领先优势在四大一线城市中列位第一--有22.9%的受访者把上海作为跳槽首选目标工作城

vdceye 太难发音了么?

2015 China Hadoop Summit 北京站 上,大家认为vdceye比较难发音,其实当时用vdceye的名字是有原因的,vdc代表 Video Data Center,其实也就是大数据的意思. 根据大家的意见,把vdceye修改为veyesys,好发音吧,由于veye 域名被抢注了,只能用veyesys,类似milestonesys. 另外把支持HDFS 录像的vdceye  改称OpenCVR, Open Source Cloud Video Recorder.