ZooKeeper客戶端地址列表的隨機原理

原文:http://nileader.blog.51cto.com/1381108/932948


在之前一個文章《ZooKeeper Java API 使用樣例》中提到,客戶端使用ZooKeeper的時候,首先會建立與ZooKeeper的連接,方法是通過調用下面這個構造方法來實現的。

  1. public ZooKeeper(String connectString, // 
  2. int sessionTimeout, // 
  3. Watcher watcher,// 
  4. boolean canBeReadOnly ) 
  5. throws IOException 

 在這個構造方法中,首先要配置的是ZK服務器的地址列表,即connectString 這個參數,這個參數通常是這樣一個格式的字符串:

  1. 192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181 

 很明顯,我們可以看到,ZK客戶端允許我們將ZK服務器的所有地址都配置在這裏,於是一個問題就來了,ZK在連接服務器過程中,是如何選擇服務器的呢?下面首先來看看ZK客戶端是如何處理這個connectString的:

  1. new ZooKeeper(“192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181”,...) 

 實例一個ZooKeeper對象的時候,會要求傳入一個地址列表的字符串,這個字符串就是ZK服務器的地址列表,用英文狀態“,“隔開

  1. ConnectStringParser connectStringParser =  
new ConnectStringParser(“192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181”); 

 之後,這個地址列表會被封裝到一個ConnectStringParser 對象中去,這個類主要就是解析傳入地址列表字符串,將其它保存在一個ArrayList中。這個對象基本結構如下,這裏我們主要關注serverAddresses這個成員

  1. public final class ConnectStringParser { 
  2.     private final String chrootPath; 
  3.     private final ArrayList<InetSocketAddress> serverAddresses = new ArrayList<InetSocketAddress>(); 

接下去,這個地址列表會被進一步封裝成StaticHostProvider對象,並且在運行過程中,一直是這個對象來維護整個地址列表。關於這個對象,我們主要關注兩點:地址列表的隨機和地址獲取這兩個過程。首先來看地址列表的隨機

  1. public StaticHostProvider(Collection<InetSocketAddress> serverAddresses) 
  2.             throws UnknownHostException { 
  3.         …… 
  4. …… 
  5.         Collections.shuffle(this.serverAddresses); 
  6.     } 

這裏可以看到,對於傳入地址列表,ZK使用java.util.Collections.shuffle(List list) 來對地址列表隨機打亂順序,注意,這個隨機過程是一次性的,也就是說,之後使用過程中一直是按照這樣的順序。再來看看地址列表被隨機打亂後,又是怎麼使用地址的

  1.  public InetSocketAddress next(long spinDelay) { 
  2.         ++currentIndex; 
  3.         if (currentIndex == serverAddresses.size()) { 
  4.             currentIndex = 0
  5.         } 
  6. …… 
  7. …… 
  8.         return serverAddresses.get(currentIndex); 
  9.     } 

看一下StaticHostProvider.next(long spinDelay) 方法就明白了。next方法的實現, 沒錯,就是“Round Robin”。簡單的說,ZK客戶端將所有Server保存在一個List中,然後隨機打亂,並且形成一個環,具體使用的時候,從0號位開始一個一個使用

另外兩個注意點

1.通過代碼,可以發現ZK本質上是通過一個List來維護地址列表的,因此,Server地址能夠重複配置,這樣能夠彌補客戶端無法設置Server權重的缺陷,但是也會加大風險。 比如: 192.168.1.1:2181,192.168.1.1:2181,192.168.1.2:2181

2.如果客戶端在進行Server切換過程中耗時過長,那麼將會收到SESSION_EXPIRED. 這也是上面第1點中的加大風險之處


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章