一.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毫秒。