ZookeeperNet太難用,寫了個RetryHelper來進行配套使用

來源:互聯網
上載者:User

標籤:des   style   blog   http   color   使用   

普通的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

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.