普通的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 = ;
private long signal = ;
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) > )
Thread.Sleep(retryDelay); if (attempSignal == )
{
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();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " FixConnectionLossAction END " + DateTime.Now.ToString());
};
helper.IfErrorThen = () => { Console.WriteLine("IfErrorThen"); }; var tasks=new List<Task>();
for (int i = ; i < ; 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来进行配套使用的更多相关文章

  1. 曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎

    曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎 写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean De ...

  2. 朱晔的互联网架构实践心得S2E1:业务代码究竟难不难写?

    注意,这是我的架构实践心得的第二季的系列文章,第一季有10篇你也可以回顾. 见https://www.cnblogs.com/lovecindywang/category/1296779.html 最 ...

  3. 浏览器主页锁定之战——IE:我太难了

    精彩回顾: 我是一个explorer的线程 我是一个杀毒软件线程 我是一个IE浏览器线程 比特宇宙-TCP/IP的诞生 产品vs程序员:你知道www是怎么来的吗? Hello, World! 我是一个 ...

  4. arithmetic-slices-ii-subsequence(太难了)

    https://leetcode.com/problems/arithmetic-slices-ii-subsequence/ 太难了... package com.company; import j ...

  5. 前阿里CEO卫哲谈阿里创业经验:如何找人、找钱、找方向?(不同的阶段分别有:时间优先、金额优先、比例优先,不要做平台,太难)

    新浪科技李根 整理报道 卫哲现在是御嘉基金的创始合伙人,他另一个更加知名的身份是阿里巴巴(B2B)前CEO,在2006年到2011年的时间里,卫哲见证了阿里巴巴如何利用人才.资本和方向选择一路壮大. ...

  6. 对不起,给pandas配表情包太难了,pandas你该这么学,No.6

    如果图片无法观看,请移步 https://blog.csdn.net/hihell 标题起的长,才能引起你的注意呢 昨天,有个家伙,留言给我说 嫌我不好好写博客 就知道给文章配表情包 在这里,郑重的回 ...

  7. ORACLE 监听日志文件太大停止写监听日志引起数据库连接不上问题

    生产库监听日志文件太大(达到4G多),发现oracle停止写监听日志,检查参数log_file,log_directory,log_status 均正常,数据库运行也正常. 经确认确实为监听日志过大引 ...

  8. ACM数论之旅11---浅谈指数与对数(长篇)(今天休息,不学太难的数论> 3<)

    c/c++语言中,关于指数,对数的函数我也就知道那么多 exp(),pow(),sqrt(),log(),log10(), exp(x)就是计算e的x次方,sqrt(x)就是对x开根号 pow()函数 ...

  9. 电商项目面试题 及mysql面试题 太难没啥用

    需要按照功能点把系统拆分,拆分成独立的功能.单独为某一个节点添加服务器.需要系统之间配合才能完成整个业务逻辑.叫做分布式.集群:同一个工程部署到多台服务器上.优点:1.把模块拆分,使用接口通信,降低模 ...

随机推荐

  1. 《深入理解Spark:核心思想与源码分析》正式出版上市

    自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...

  2. C# 基础(2)

    打开一个解决方案,以.sin后缀名,.csproj是项目文件的后缀名. Console.WriteLine("这是我的第二个项目!");你想显示的内容 Console.ReadKe ...

  3. img图片放大控件 lightbox.js

    1.引入相关js,css jquery-1.7.2.min.js,lightbox.css,lightbox.js   2 图片增加<a href="大图片地址" rel=& ...

  4. jquery实现checkbox的全选

    <html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> < ...

  5. Event --mysql的scheduler.md

    事件调度器event 相当于oracle scheduler CREATE [DEFINER = { user | CURRENT_USER }] EVENT [IF NOT EXISTS] even ...

  6. SR触发器和JK触发器

    SR触发器(电平触发器) 基本RS触发器的逻辑方程为:Q(n+1)=一S+RQ(n); 约束方程:R+S=1; 根据上述两个式子得到它的四种输入与输出的关系: 1.当R端有效(0),S端无效时(1), ...

  7. SQLSERVER 2012之AlwaysOn -- 一次硬件升级引发的问题

    这是上周遇到的一个案例:对已有的硬件进行升级而引发的问题,期间还触发了一个比较严重的BUG,可谓多灾多难:不过值得庆幸的是,在一连串连锁问题出现的时候,并没有出现人工操作失误(这往往是在处理故障中风险 ...

  8. input text 的事件及方法

    事件 描述onactivate 当对象设置为活动元素时触发.onafterupdate 当成功更新数据源对象中的关联对象后在数据绑定对象上触发.onbeforeactivate 对象要被设置为当前元素 ...

  9. java web图片显示到浏览器

    今天研究了一下午,图片显示问题. jsp中获取绝对路径的方法:String contextPath = request.getContextPath();String path = request.g ...

  10. paip.哈米架构CAO.txt

    paip.哈米架构CAO.txt 智能语义搜索方法,建立了学习机,通过对用户点击情况的处理,对知识库进行及时更新,并将搜索结果根据关联度进行排序及重新排序,使用户能快速查询信息,从而能不断适应用户使用 ...