Curator是zookeeper的客户端之一,以下通过模拟实现dubbo-Admin的功能来介绍Curator.
我们都知道,dubbo一般都使用zk来做目录服务,dubbo在zk上注册的根节点就“/dubbo”,所以我们通过节点查询来实现查询和监控服务状态。
1.引入curator
<dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.8.0</version> </dependency>
2.构造zk的链接
package com.zk;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class ZkClientFactory {
private static CuratorFramework client;
//构造全局的zk链接对象。当然也可以通过配置增加更多的参数
public static CuratorFramework getInstance(String url){
if(null == client){
synchronized(ZkClientFactory.class){
if(null == client){
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();
client = builder.connectString(url)
.sessionTimeoutMs(3000)
.connectionTimeoutMs(3000)
.canBeReadOnly(false)
.retryPolicy(new ExponentialBackoffRetry(1000, Integer.MAX_VALUE))
.namespace(null)
.defaultData(null)
.build();
client.start();
}
}
}
return client;
}
}
3.查询dubbo服务并打印
package com.zk;
import java.net.URLDecoder;
import java.util.List;
import org.apache.curator.framework.CuratorFramework;
public class DubboAdmin {
private static final String ZK_ADDRESS = "127.0.0.1:2182";
private static String serverName = "MyService";
private static CuratorFramework client = ZkClientFactory.getInstance(ZK_ADDRESS);
public static void main(String[] args) throws Exception {
List<String> services = client.getChildren().forPath("/dubbo");
if(null == services || services.isEmpty()){
System.out.println("No service in Zk...");
System.exit(1);
}
System.out.println("Search Service ["+serverName+"] start...");
for(String str : services){
if(str.contains(serverName)){
printDetail(str);
}
}
System.out.println("Search Service ["+serverName+"] end." );
}
//打印单个服务节点信息
private static void printDetail(String str) throws Exception{
System.out.println("==================================");
System.out.println("CurrentNode is:"+ str);
List<String> children = client.getChildren().forPath("/dubbo/"+str);
for(String child :children){
List<String> nodes = client.getChildren().forPath("/dubbo/"+str+"/"+child);
System.out.println(" NodeName:"+child);
for(String node :nodes){
System.out.println(" "+URLDecoder.decode(node));
}
}
}
}
4.打印结果
Search Service [CouponService] start...
==================================
CurrentNode is:com.service.MyService
NodeName:consumers
NodeName:routers
NodeName:providers
dubbo://192.168.62.85:20882/com......
dubbo://192.168.62.85:23333/com......
NodeName:configurators
==================================
存在的疑问:
client.start();这个方法调后,会起线程去连zk,不管是否连接成功,client的状态都已经是started.无法判断连接状态。如果连接未成功,执行任何操作都会被阻塞。那怎么在应用启动时判断是否连接成功?