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{
/**
*/
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.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();
threadarray[i].join();
mainstat.settertime = system.currenttimemillis() - begin;
begin = system.currenttimemillis();
threadarray[i] = new getterthread(statarray[i]);
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)");
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() {
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 {
getterthread(workerstat stat) {
//讀取節點資料
zk.getdata(nodepath, false, null);
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) {
* 設定節點資料
* @throws exception
public void setdata(string path,string data) throws exception{
zk.setdata(path, data.getbytes(), -1);
system.out.println("set data:"+"testsetdata");
* 讀取節點資料
public void getdata() throws exception{
system.out.println("get data:");
* 删除節點
* @param path
public void delete(string path) throws exception{
system.out.println("删除節點:"+path);
//如果版本号與znode的版本号不一緻,将無法删除,是一種樂觀加鎖機制;如果将版本号設定為-1,不會去檢測版本,直接删除;
zk.delete(path, -1);
* 關閉連接配接
public void close() {
zk.close();
} catch (interruptedexception e) {
相關功能代碼中都已經注釋清楚。我們看一下測試下來的結果: 寫入資料:
讀取資料:
由上兩張圖我們可以得知:
1、寫入(set)資料時,單個線程執行是最快的,而讀取(get)資料則是4或5個線程并發是最快的。
2、每個節點存儲的資料不能超過1m(在zookeeper預設配置的情況下,如果寫入的資料為1m會報錯,無法寫入資料,是以所有應用寫入的資料必須<1m)
3、單個寫入資料的體積越大,處理速度越慢,響應時間越長。
4、會管應用中寫入的資料最大的是16方畫面合成的時候,此時寫入的資料可能大于4k,另外16方畫面合成時候zk節點存放的資料(json)是包含大量空格和換行的(在zk節點中,空格和換行也是占大小的),是以建議壓縮json資料。
5、測試過程中産生的log檔案對磁盤的消耗和占用較大,建議定時删除曆史log和shapshot
最新内容請見作者的github頁:http://qaseven.github.io/