關于Zookeeper,之前有過幾篇文章已經介紹過了,因此本文不贅述。 本次小編對單機部署的Zookeeper的讀、寫進行了一次簡單性能測試。 性能測試腳本由java完成,具體請看代碼清單:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
package com.kiven.test; import java.util.List; import java.util.concurrent.CountDownLatch; import org.apache.log4j.PropertyConfigurator; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; public class Test{ /** * server列表, 以逗號分割 */ protected static String hosts = "172.16.217.148:2181"; /** * 連接的超時時間, 毫秒 */ private final int SESSION_TIMEOUT = 5000; private CountDownLatch connectedSignal = new CountDownLatch(1); protected static ZooKeeper zk; private static String nodePath = "/Test/test1"; //static String data = "a very long string about data to set to zookeeper"; static int threads = 10; //線程數 static int runs = 1000; //迭代次數 static int start = 0; //none static int size = 1024*4; //寫入數據的大小,單位:字節 static byte[] testdata; //測試數據 public static void main(String[] args) throws Exception { PropertyConfigurator.configure("log4j.properties"); //生成寫入的數據,大小size字節 testdata = new byte[size]; for(int i=0;i<size;i++){ testdata[i] = 'A'; } Test test = new Test(); //連接 test.connect(); WorkerStat[] statArray = new WorkerStat[threads]; Thread[] threadArray = new Thread[threads]; WorkerStat mainStat = new WorkerStat(); mainStat.runs = runs * threads; long begin = System.currentTimeMillis(); for (int i = 0; i < threads; i++) { statArray[i] = new WorkerStat(); statArray[i].start = start + i * runs; statArray[i].runs = runs; threadArray[i] = new SetterThread(statArray[i]); threadArray[i].start(); } for (int i = 0; i < threads; i++) { threadArray[i].join(); } mainStat.setterTime = System.currentTimeMillis() - begin; begin = System.currentTimeMillis(); for (int i = 0; i < threads; i++) { threadArray[i] = new GetterThread(statArray[i]); threadArray[i].start(); } for (int i = 0; i < threads; i++) { threadArray[i].join(); } mainStat.getterTime = System.currentTimeMillis() - begin; WorkerStat totalStat = new WorkerStat(); System.out.println("Test over!!"); System.out.println("Thread("+threads+")\truns\tset time(ms)\tget time(ms)"); for (int i = 0; i < threads; i++) { totalStat.runs = totalStat.runs + statArray[i].runs; totalStat.setterTime = totalStat.setterTime + statArray[i].setterTime; totalStat.getterTime = totalStat.getterTime + statArray[i].getterTime; } System.out.println("Total\t\t" + totalStat.runs + "\t"+ totalStat.setterTime + "\t\t" + totalStat.getterTime); System.out.println("Avg\t\t" + runs + "\t" + totalStat.setterTime/ threads + "\t\t" + totalStat.getterTime / threads); System.out.println("TPS\t\t\t" + 1000 * totalStat.runs/ totalStat.setterTime + "\t\t" + 1000 * totalStat.runs/ totalStat.getterTime); System.out.println("\nMain\t\t" + mainStat.runs + "\t"+ mainStat.setterTime + "\t\t" + mainStat.getterTime); System.out.println("TPS\t\t" + 1000 * mainStat.runs/ mainStat.setterTime + "\t\t" + 1000 * mainStat.runs/ mainStat.getterTime); } private static class WorkerStat { public int start, runs; public long setterTime, getterTime; public WorkerStat() { start = runs = 0; setterTime = getterTime = 0; } } private static class SetterThread extends Thread { private WorkerStat stat; SetterThread(WorkerStat stat) { this.stat = stat; } public void run() { long begin = System.currentTimeMillis(); for (int i = stat.start; i < stat.start + stat.runs; i++) { //寫入節點數據 try { zk.setData(nodePath, testdata, -1); } catch (Exception e) { e.printStackTrace(); } } long end = System.currentTimeMillis(); stat.setterTime = end - begin; } } private static class GetterThread extends Thread { private WorkerStat stat; GetterThread(WorkerStat stat) { this.stat = stat; } public void run() { long begin = System.currentTimeMillis(); for (int i = stat.start; i < stat.start + stat.runs; i++) { //讀取節點數據 try { zk.getData(nodePath, false, null); } catch (Exception e) { e.printStackTrace(); } } long end = System.currentTimeMillis(); stat.getterTime = end - begin; } } //=============================================================================== /** * 連接zookeeper server */ public void connect() throws Exception { zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new ConnWatcher()); // 等待連接完成 connectedSignal.await(); } /** * * @author Kiven * */ public class ConnWatcher implements Watcher{ public void process(WatchedEvent event) { // 連接建立, 回調process接口時, 其event.getState()為KeeperState.SyncConnected if (event.getState() == KeeperState.SyncConnected) { // 放開閘門, wait在connect方法上的線程將被喚醒 connectedSignal.countDown(); } } } /** 以下為各個參數的詳細說明: path. znode的路徑. data. 與znode關聯的數據. acl. 指定權限信息, 如果不想指定權限, 可以傳入Ids.OPEN_ACL_UNSAFE. 指定znode類型. CreateMode是一個枚舉類, 從中選擇一個成員傳入即可. */ /** * 創建持久化節點 */ public void create(String Path, byte[] data) throws Exception { zk.create(Path, data, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("創建節點:"+Path); System.out.println("================="); } /** * *獲取節點信息 *@author kiven *@createDate 2013-01-16 15:17:22 *@param path *@throws KeeperException *@throws InterruptedException */ public void getChild(String path) throws KeeperException, InterruptedException{ try{ List list=zk.getChildren(path, false); if(list.isEmpty()){ System.out.println(path+"中沒有節點"); }else{ System.out.println(path+"中存在節點"); for(String child:list){ System.out.println("節點為:"+child); } } }catch (KeeperException.NoNodeException e) { e.printStackTrace(); } } /** * 設置節點數據 * @throws Exception */ public void setData(String path,String data) throws Exception{ zk.setData(path, data.getBytes(), -1); System.out.println("set Data:"+"testSetData"); } /** * 讀取節點數據 * @throws Exception */ public void getData() throws Exception{ System.out.println("get Data:"); zk.getData(nodePath, false, null); } /** * 刪除節點 * @param path * @throws Exception */ public void delete(String path) throws Exception{ System.out.println("刪除節點:"+path); //如果版本號與znode的版本號不一致,將無法刪除,是一種樂觀加鎖機制;如果將版本號設置為-1,不會去檢測版本,直接刪除; zk.delete(path, -1); } /** * 關閉連接 */ public void close() { try { zk.close(); } catch (InterruptedException e) { e.printStackTrace(); } } } |
原文轉自:http://www.diggerplus.org/archives/2958