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中某一個元素重復的參數