一.dubbo应用zk目的


作为服务注册中心,服务消费方从zk上获取服务提供方信息。新增服务提供方或者服务提供方down机,能够及时的通知到服务消费方。



二.注册服务,对于zk的部分源码解读



对于注册一个服务,会在zk上创建相应的zNode结点。


这时抛出一个问题:dubbo注册服务时使用的是持久结点还是临时结点?



首先临时结点不能有子结点。


临时结点有个优点是当某个创建这个临时结点的session超时会触发相应的watch事件通知到相应的服务消费方。


这里有个需求就是服务提供方如果挂了,可以通知服务消费方。



而为了节省存储空间,对于相同的服务接口,它们的父结点是相同的。


比如:服务接口【com.test.cartservice.service.CartService】,则在zk中存储如下:


/dubbo/com.test.cartservice.service.CartService/providers/dubbo%3A%2F%2F172.17.0.234%3A20880%2Fcom.test.cartservice.service.CartService%3FaddCartItem.retries%3D0%26anyhost%3Dtrue%26application%3Dcart-app%26deleteCartItem.retries%3D0%26descreaseSkuNumForCartOfUser.retries%3D0%26dubbo%3D2.5.3%26increaseSkuNumForCartOfUser.retries%3D0%26interface%3Dcom.test.cartservice.service.CartService%26methods%3DgetCartCountByUserId%2CdescreaseSkuNumForCartOfUser%2CincreaseSkuNumForCartOfUser%2CaddCartItem%2CgetCartVoByUserId%2CdeleteCartItem%26pid%3D8025%26side%3Dprovider%26timestamp%3D1505539741539 

 
 
 
 

  由于临时结点不能有子结点,所以/dubbo结点,/com.test.cartservice.service.CartService结点,/providers均为持久结点。 

 
 
 
 

  整个创建服务提供方zk结点的代码如下: 

 

  核心的类是:AbstractZookeeperClient 

 

  public void create(String path, boolean ephemeral) { 

 

  int i = path.lastIndexOf('/'); 

 

  if (i > 0) { 

 

  create(path.substring(0, i), false); //除最后一个结点,其它结点都是持久结点,这里递归调用 

 

  } 

 

  if (ephemeral) { 

 

  createEphemeral(path); 

 

  } else { 

 

  createPersistent(path); 

 

  } 

 

  } 

 

  create方法入参:path为【/dubbo/com.test.cartservice.service.CartService/providers/dubbo%3A%2F%2F172.17.0.234%3A20880%2Fcom.test.cartservice.service.CartService%3FaddCartItem.retries%3D0%26anyhost%3Dtrue%26application%3Dcart-app%26deleteCartItem.retries%3D0%26descreaseSkuNumForCartOfUser.retries%3D0%26dubbo%3D2.5.3%26increaseSkuNumForCartOfUser.retries%3D0%26interface%3Dcom.test.cartservice.service.CartService%26methods%3DgetCartCountByUserId%2CdescreaseSkuNumForCartOfUser%2CincreaseSkuNumForCartOfUser%2CaddCartItem%2CgetCartVoByUserId%2CdeleteCartItem%26pid%3D8025%26side%3Dprovider%26timestamp%3D1505539741539】


去除最后一个结点,也就是providers后面的结点,进行递归创建结点,类型为持久结点。


最后一个结点是临时结点,也就是实际的服务提供方信息。



所有的watch实现都在创建Zookeeper客户端对象时创建。


例:


zk=new ZooKeeper(host,5000,new Watcher(){


public void process(WatchedEvent event){


// watch事件处理


}


});



而真正的watch监听则是在具体调用zk相应方法时监听。


可以设置监听的api有:


getData(), 可以设置数据变化监听事件


getChildren(), // 可以设置子结点变化监听事件


create(), // 可以设置当前结点创建变化监听事件


delete(), / 可以设置当前结点删除变化监听事件



而dubbo消费者也是通过getChildren来进行watch事件注册,对于上面的cart服务例子,则监听的zNode为:


/dubbo/com.test.cartservice.service.CartService/providers


当这个结点下面增加或减少子结点时(代表服务提供方的变化),则会触发watch事件。然后服务消费方会通过getChildren方法来获取该结点下当前最新的所有服务提供方信息,然后更新本地服务方列表。


默认服务提供方与zk服务器的超时时间为30000毫秒。