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 = ;
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();
}
运行:

ZookeeperNet太难用,写了个RetryHelper来进行配套使用的更多相关文章
- 曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎
曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎 写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean De ...
- 朱晔的互联网架构实践心得S2E1:业务代码究竟难不难写?
注意,这是我的架构实践心得的第二季的系列文章,第一季有10篇你也可以回顾. 见https://www.cnblogs.com/lovecindywang/category/1296779.html 最 ...
- 浏览器主页锁定之战——IE:我太难了
精彩回顾: 我是一个explorer的线程 我是一个杀毒软件线程 我是一个IE浏览器线程 比特宇宙-TCP/IP的诞生 产品vs程序员:你知道www是怎么来的吗? Hello, World! 我是一个 ...
- arithmetic-slices-ii-subsequence(太难了)
https://leetcode.com/problems/arithmetic-slices-ii-subsequence/ 太难了... package com.company; import j ...
- 前阿里CEO卫哲谈阿里创业经验:如何找人、找钱、找方向?(不同的阶段分别有:时间优先、金额优先、比例优先,不要做平台,太难)
新浪科技李根 整理报道 卫哲现在是御嘉基金的创始合伙人,他另一个更加知名的身份是阿里巴巴(B2B)前CEO,在2006年到2011年的时间里,卫哲见证了阿里巴巴如何利用人才.资本和方向选择一路壮大. ...
- 对不起,给pandas配表情包太难了,pandas你该这么学,No.6
如果图片无法观看,请移步 https://blog.csdn.net/hihell 标题起的长,才能引起你的注意呢 昨天,有个家伙,留言给我说 嫌我不好好写博客 就知道给文章配表情包 在这里,郑重的回 ...
- ORACLE 监听日志文件太大停止写监听日志引起数据库连接不上问题
生产库监听日志文件太大(达到4G多),发现oracle停止写监听日志,检查参数log_file,log_directory,log_status 均正常,数据库运行也正常. 经确认确实为监听日志过大引 ...
- ACM数论之旅11---浅谈指数与对数(长篇)(今天休息,不学太难的数论> 3<)
c/c++语言中,关于指数,对数的函数我也就知道那么多 exp(),pow(),sqrt(),log(),log10(), exp(x)就是计算e的x次方,sqrt(x)就是对x开根号 pow()函数 ...
- 电商项目面试题 及mysql面试题 太难没啥用
需要按照功能点把系统拆分,拆分成独立的功能.单独为某一个节点添加服务器.需要系统之间配合才能完成整个业务逻辑.叫做分布式.集群:同一个工程部署到多台服务器上.优点:1.把模块拆分,使用接口通信,降低模 ...
随机推荐
- 《深入理解Spark:核心思想与源码分析》正式出版上市
自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...
- C# 基础(2)
打开一个解决方案,以.sin后缀名,.csproj是项目文件的后缀名. Console.WriteLine("这是我的第二个项目!");你想显示的内容 Console.ReadKe ...
- img图片放大控件 lightbox.js
1.引入相关js,css jquery-1.7.2.min.js,lightbox.css,lightbox.js 2 图片增加<a href="大图片地址" rel=& ...
- jquery实现checkbox的全选
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> < ...
- Event --mysql的scheduler.md
事件调度器event 相当于oracle scheduler CREATE [DEFINER = { user | CURRENT_USER }] EVENT [IF NOT EXISTS] even ...
- SR触发器和JK触发器
SR触发器(电平触发器) 基本RS触发器的逻辑方程为:Q(n+1)=一S+RQ(n); 约束方程:R+S=1; 根据上述两个式子得到它的四种输入与输出的关系: 1.当R端有效(0),S端无效时(1), ...
- SQLSERVER 2012之AlwaysOn -- 一次硬件升级引发的问题
这是上周遇到的一个案例:对已有的硬件进行升级而引发的问题,期间还触发了一个比较严重的BUG,可谓多灾多难:不过值得庆幸的是,在一连串连锁问题出现的时候,并没有出现人工操作失误(这往往是在处理故障中风险 ...
- input text 的事件及方法
事件 描述onactivate 当对象设置为活动元素时触发.onafterupdate 当成功更新数据源对象中的关联对象后在数据绑定对象上触发.onbeforeactivate 对象要被设置为当前元素 ...
- java web图片显示到浏览器
今天研究了一下午,图片显示问题. jsp中获取绝对路径的方法:String contextPath = request.getContextPath();String path = request.g ...
- paip.哈米架构CAO.txt
paip.哈米架构CAO.txt 智能语义搜索方法,建立了学习机,通过对用户点击情况的处理,对知识库进行及时更新,并将搜索结果根据关联度进行排序及重新排序,使用户能快速查询信息,从而能不断适应用户使用 ...