普通的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.把模块拆分,使用接口通信,降低模 ...
随机推荐
-
C#绘制立体三维饼状图
转载自原文 C#绘制立体三维饼状图(超酷) 内容原文地址:LINK [翻译]Julijan Sribar著3D Pie Chart一个用于绘制立体三维饼状图的C#类库[简介]本文的想法就是创建一个独立 ...
-
C#_约束 实现可排序单链表
using System; using System.Collections.Generic; using System.Linq; using System.Text; /* 使用 约束 实现可排序 ...
-
django入门教程(下)
在两篇文章帮你入门Django(上)一文中,我们已经做了一个简单的小网站,实现了保存用户数据到数据库,以及从后台数据库读取数据显示到网页上这两个功能. 看上去没有什么问题了,不过我们可以让它变得更加完 ...
-
删除SVN文件 Delete SVN Folders.reg
批量删除文件夹里的SVN 文件 ------------------------------------------------------------------------------------ ...
-
TCP:三次握手、四次握手、backlog及其他
TCP是什么 首先看一下OSI七层模型: 然后数据从应用层发下来,会在每一层都加上头部信息进行封装,然后再发送到数据接收端,这个基本的流程中每个数据都会经过数据的封装和解封的过程,流程如下图所示: 在 ...
-
出现“Unable to resolve target &#39;android-XXX&#39;”怎么处理?
这句话的中文意思就是说安卓API版本没有能适配22的,需要将sdk更新一下,必要的话,adt都要跟着更新,但就我尝试来看,还是要先更新adt,然后您或许发现,这个表单好不容易刷出来,但是没有我们想要的 ...
-
linux-php5.6-安装sftp扩展
一. 更新gc库,添加libssh2库 yum -y install libstdc libgomp cpp gcc libgfortran libssh2 libssh2-devel gcc-gfo ...
-
iis7 设置自定义404页面无效解决方案
想给自己做的的网站自定义一个404页面,开始 双击红框提示的错误页图标 双击上图红框提示的所示404行 修改上图红框提示的内容如下:我是直接在根目录放了一个自己做的404.html,实际情况要填写你自 ...
-
Packt发布了2018年技能提升报告
2018年技能提升报告Skill Up 2018 - Developer Skills Report | PACKT Bookshttps://www.packtpub.com/skill-up-20 ...
-
【转载】InstallShield 生成安装日志
msiexec.exe /p "C:\Documents and Settings\qa\Desktop\8.3 Patch.msp" /l*v c:\log85gold.log ...