zkclient的使用记录
1.最近有一个需求是导出zk上的注册服务列表,zkclient做这个比较方便,所以就使用过程做一些记录
2.需求分析
本次这个需求需要实现2个功能:
a.取出所有分组下的服务列表,并计算提供者的个数,最终以 分组 接口 提供者个数这样的格式输出到表格
b.取出分组下的接口,截取包名,并计算同一分组下的同一包名的个数,最终以 分组 包名 个数这样 的格式输出到表格
3.代码实现
a.首先获得zk地址,设置session超时时间
1 /** zookeeper地址 */ 2 static final String CONNECT_ADDR = "172.16.80.44:2181";
3 /** session超时时间 */
4 static final int SESSION_OUTTIME = 10000;//ms
b.获得与zk的连接
1 ZkClient zkc = new ZkClient(new ZkConnection(CONNECT_ADDR), SESSION_OUTTIME);
c.获得zk下的所有分组
1 List<String> children = zkc.getChildren("/");// "/"代表获得zk下的根节点目录,即Dubbo的分组目录
d.对chlidren进行遍历,即对所有分组进行遍历,来获得服务的接口目录,然后对获得的接口列表进行遍历,获得所有接口名称
1 for (String group : children) { 2 List<String> interfaces = zkc.getChildren("/" + group);//这一步获得分组下的所有接口
for (String interfaceName : interfaces) {//对接口列表进行遍历
System.out.println(interfaceName);
//List<String> msg = zkc.getChildren("/" + group + "/" + interfaceName + "/providers");//这样可以获得接口的提供者
}
3 }
这一部分主要介绍了如何获得zk连接,并获得列表的过程,主要是通过zkc.getChildren()实现的,通过group+interface+providers获得分组,接口,提供者等信息,providers.size()获得提供者个数
下面给出完整 的例子
4.完整例子
这个例子实现了获取接口列表,计算提供者个数,截取接口的包名等功能,最后输出到.csv文件。最后还进行了csv文件的合并
a.关于截取包名这个功能,想到了用substring这个方法,接口全路径名到接口名那出现大写字母,所以对于全路径名,截取大写字母之前的路径
1 public static String getString(String str){ 2 int index = -1; 3 char[] chars = str.toCharArray(); 4 if(chars!=null){ 5 for(int i=0; i<chars.length; i++){ 6 if((chars[i] >= 'A') && (chars[i] <= 'Z')){ 7 index = i; 8 break; 9 } 10 } 11 12 } 13 return str.substring(0, index-1);//考虑到大写字母之前还有一个点,所以index-1返回,zk上有的分组下面没有接口,会发生Index=-2越界问题,建议排除掉这些分组 14 }
b.关于文件输出问题,采用了PrintWriter这个类
1 PrintWriter out = null; 2 try { 3 out = new PrintWriter(new BufferedWriter(new FileWriter("11.csv")));//11.csv是记录输出的位置 4 out.println("group,prefix,number");//以","分隔目录在表格里这是三个单元格的开头
out.println(group + "," + key + "," + map.get(key));//这是具体的输出内容,分组,包名,个数
5 }catch (Exception e){
e.printStackTrace();
}
c.关于截取包名之后如何计数的问题,在获得一个分组的所有接口列表后,进行包名截取,然后new一个map,key=包名,value=相同包名重复的次数
1
Map<String, Integer> map = new HashMap<String, Integer>();//new HashMap用于存放包名和其在一个分组下出现的次数
for (String interfaceName : interfaces) {//遍历接口列表 2 try { 3 String packageName = getString(interfaceName);//截取包名 4 Integer times = map.get(packageName);//先从map里取值,看能不能取到值,能取到,times+1,不能取到就放入map里,times=1 5 if (null != times) { 6 times = times + 1; 7 map.put(packageName, times); 8 } else { 9 map.put(packageName, 1); 10 } 11 12 List<String> msg = zkc.getChildren("/" + group + "/" + interfaceName + "/providers"); 13 for (String s:msg) { 14 System.out.println(s); 15 } 16 17 18 } catch (Exception e) { 19 e.printStackTrace(); 20 } 21 }//循环结束 22 System.out.println(map); //这个map存放着对象的hascode值和重复次数 23 Set<String> keys = map.keySet();//key值的集合,就是对象的 hascode的值 24 for (String key : keys) { 25 out.println(group + "," + key + "," + map.get(key));//这里输出,分组,包名,同一包名的次数 26 }
d.由于是要实现2个需求,所以最终文件输入到了2个csv文件中,现在需要将2个csv整合到一起,将2个csv文件放到同一个文件夹中,新建一个excel文件,打开excel文件,在sheet上右击,选择检查代码
1 Private Sub copy_csvfile_to_excel() 2 3 Dim MyPath$, myFile$, AK As Workbook 4 Application.ScreenUpdating = False 5 MyPath = ThisWorkbook.Path & "\" 6 myFile = Dir(MyPath & "*.csv") 7 Do While myFile <> "" 8 If myFile <> ThisWorkbook.Name Then 9 Set AK = Workbooks.Open(MyPath & myFile) 10 AK.Sheets(1).Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count) 11 Workbooks(myFile).Close 12 End If 13 myFile = Dir 14 Set AK = Nothing 15 Loop 16 Application.ScreenUpdating = True 17 ActiveWorkbook.Save 18 MsgBox "汇总完成,请查看!", 64, "提示" 19 End Sub
e.下面是这个例子的完整代码
1 package com.alibaba.dubbo.zkc.zkc; 2 3 import com.alibaba.dubbo.common.utils.StringUtils; 4 import org.I0Itec.zkclient.ZkClient; 5 import org.I0Itec.zkclient.ZkConnection; 6 7 import java.io.BufferedWriter; 8 import java.io.FileWriter; 9 import java.io.IOException; 10 import java.io.PrintWriter; 11 import java.util.*; 12 13 14 /** 15 16 17 18 */ 19 public class ZKClientBase { 20 /** zookeeper地址 */ 21 static final String CONNECT_ADDR = "127.0.0.1:2181";//zk地址选择自己需要的,多个zk以逗号分隔,"192.168.1.171:2181,192.168.1.172:2181,192.168.1.173:2181" 22 /** session超时时间 */ 23 static final int SESSION_OUTTIME = 10000;//ms 24 25 public static String getString(String str){ 26 int index = -1; 27 char[] chars = str.toCharArray(); 28 if(chars!=null){ 29 for(int i=0; i<chars.length; i++){ 30 if((chars[i] >= 'A') && (chars[i] <= 'Z')){ 31 index = i; 32 break; 33 } 34 } 35 36 } 37 return str.substring(0, index-1); 38 } 39 40 41 42 public static void main(String[] args) throws Exception { 43 ZkClient zkc = new ZkClient(new ZkConnection(CONNECT_ADDR), SESSION_OUTTIME); 44 45 PrintWriter out = null; 46 try { 47 out = new PrintWriter(new BufferedWriter(new FileWriter("packageNumber44.csv"))); 48 out.println("group,prefix,number"); 49 List<String> children = zkc.getChildren("/"); 50 Map<String, Integer> map = new HashMap<String, Integer>(); 51 for (String group : children) { 52 if (!group.equals("BSSTask") && !group.equals("zookeeper") && !group.equals("ocs_root")&&!group.equals("ZMQ")) { 53 List<String> interfaces = zkc.getChildren("/" + group); 54 //System.out.println(group); 55 for (String interfaceName : interfaces) { 56 try { 57 String packageName = getString(interfaceName); 58 Integer times = map.get(packageName); 59 if (null != times) { 60 times = times + 1; 61 map.put(packageName, times); 62 } else { 63 map.put(packageName, 1); 64 } 65 if (interfaceName.equals("com.ztesoft.inf.hsf.service.ReceiveHBResult")||interfaceName.equals("com.ztesoft.bss.svcability")){ 66 List<String> msg = zkc.getChildren("/" + group + "/" + interfaceName + "/providers"); 67 for (String s:msg) { 68 System.out.println(s); 69 } 70 71 } 72 } catch (Exception e) { 73 e.printStackTrace(); 74 } 75 }//循环结束 76 System.out.println(map); //这个map存放着对象的hascode值和重复次数 77 Set<String> keys = map.keySet();//key值的集合,就是对象的 hascode的值 78 for (String key : keys) { 79 out.println(group + "," + key + "," + map.get(key)); 80 } 81 } 82 } 83 84 } catch (IOException e) { 85 e.printStackTrace(); 86 } finally { 87 if (out != null) { 88 out.close(); 89 } 90 } 91 92 93 } 94 }
5.简单总结
网上的例子大多是自己在zk上增加和删除节点,监听节点的变化等,本次我的需求是自己去zk上获取数据,参考了网上给出的例子,实现了自己的需求,第一次写随笔,很多细节处理的都不好,如带来困扰,敬请谅解
6.参考链接
https://blog.csdn.net/t1dmzks/article/details/78440717 //zkclient用法
https://blog.csdn.net/u011089523/article/details/53421333?locationNum=14&fps=1 //将多个csv文件写入一个excel的不同sheet中
https://www.cnblogs.com/wang-zai/p/7799778.html //截取第一个大写字母前的字符串
https://blog.csdn.net/jie1991liu/article/details/50424304 //计算一个list中某一个元素重复的参数