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.无法判断连接状态。如果连接未成功,执行任何操作都会被阻塞。那怎么在应用启动时判断是否连接成功?