同樣的程序,在centos和ubuntu上都沒有問題,在solaris上問題卻多多,據說是solaris管理更加嚴格。
zookeeper_init方法,在傳入一個錯誤的host也能初始化出一個非空的handle,只能通過state去判斷是否連接上。
另外,在centos上使用zookeeper_mt才能連上zk,而在solaris上卻不行。
分析src/c中的兩個工具cli_st和cli_mt,發現cli_mt連不上,而cli_st可以連接。於是興沖沖的將編譯選項的庫改為了-lzookeeper_st,結果返回的handle非空,高興壞了,以為成功了,結果呢~,狀態顯示為連接失敗:error code 999,這就是還沒有連接上的表現。
於是開始分析為什么cli_st工具可以連接上,代碼/src/cli.c文件中沒有什么特殊的,那就應該是編譯選項的問題了:
gcc -DHAVE_CONFIG_H -I. -I./include -I./tests -I./generated -D_POSIX_PTHREAD_SEMANTICS -Wall -Werror -g -O0 -D_GNU_SOURCE -MT cli.o -MD -MP -MF .deps/cli.Tpo -c -o cli.o `test -f 'src/cli.c' || echo './'`src/cli.c mv -f .deps/cli.Tpo .deps/cli.Po /bin/sh ./libtool --tag=CC --mode=link gcc -Wall -Werror -g -O0 -D_GNU_SOURCE -o cli_st cli.o libzookeeper_st.la libtool: link: gcc -Wall -Werror -g -O0 -D_GNU_SOURCE -o cli_st cli.o ./.libs/libzookeeper_st.a -lnsl -lsocket -lm
首先要弄懂libzookeeper_mt.so 和 libzookeeper_st.so有啥區別:
zookeeper的C客戶端分為mt庫和st庫(多線程和單線程),一般操作都是以多線程庫為主。
先記錄到這里,稍后給結果。
問題原因:
關於C開發,zookeeper提供了兩個庫:zookeeper_st(單線程庫)與zookeeper_mt(多線程庫)。zookeeper_st放棄了事件循環,可在事件驅動的應用程序中使用。而zookeeper_mt更加易用,與Java API類似,創建一個網絡IO線程和一個事件分發線程,用來維護連接和執行回調。
在具體使用上,zookeeper_st僅提供了異步API與回調,用以集成至應用程序的事件循環。它只是為了支持pthread庫不可用或不穩定的平台而存在,例如FreeBSD 4.x。除此以外的其他情況,應使用提供同步與異步兩種API的zookeeper_mt。
采用zookeeper_mt庫的zookeeper客戶端使用了3個線程:
線程1是業務邏輯層,負責與用戶直接交互,主要是zookeeper庫提供的API
線程2是網絡IO層,負責與zookeeper服務端的網絡通信,包括發送業務邏輯層的API調用生成的請求數據、服務端的響應數據、服務端的watch事件數據
線程3是事件處理層,負責執行watch回調
問題是在要將程序改為事件驅動非常麻煩,API也需要由同步改為異步,工作量相當大,接下來我們需要看看為什么在solaris上不能用多線程
最終解決方法:
最終使用gdb調試c目錄下的cli_mt工具,找到connect出錯的地方,在zookeeper.c 1612行,socket連接connect時出錯。這里只打印出了錯誤編號errno,但是編號值為0,應該不對。可能這個編號不是線程安全的,可能是被別的線程改了值。
因此添加了perror來打印具體的錯誤:Operation now in progress
搜索了下該錯誤,說是套接字阻塞,把fcntl(x,x, O_NONBLOCK)放在connect之后 居然就沒有這個錯誤了,於是也試試,竟然就解決了。
詳解:引用自http://www.bkjia.com/article/29653.html
zookeeper 的多線程和單線程庫使用對比
我們都知道zookeeper提供了兩個庫,zookeeper_st和 zookeeper_mt。
前者是單線程庫,僅僅提供了異步API和集成在應用程序實現循環中的回調函數,這個庫是為了支持pthread庫不支持或者不穩定的系統而存在的。使用過程中要自己通過zoo_interest和zoo_process實現事件處理及通知機制。
其他情況下應該使用后者多線程庫。因為它同時支持同步和異步API。使用起來也方便很多,可以看我的例子。
The package includes two shared libraries: zookeeper_st and zookeeper_mt. The former only provides the asynchronous APIs and callbacks for integrating into the application's event loop. The only reason this library exists is to support the platforms were a pthread library is not available or is unstable (i.e. FreeBSD 4.x). In all other cases, application developers should link with zookeeper_mt, as it includes support for both Sync and Async API.
OK,talk is cheap。
單線程庫使用示例:
在zookeeper上先創建/xyz才能執行成功,因為st庫僅支持異步,而異步create沒有時序保證。 該程序可以監控/xyz節點及子節點的變化。
#include
#include
#include string.h>
#include
#include
#include
#define TRUE 1static const char* state2String(int state)
{
if (state == 0)return "CLOSED_STATE";
if (state == ZOO_CONNECTING_STATE)return "CONNECTING_STATE";
if (state == ZOO_ASSOCIATING_STATE)return "ASSOCIATING_STATE";
if (state == ZOO_CONNECTED_STATE)return "CONNECTED_STATE";
if (state == ZOO_EXPIRED_SESSION_STATE)return "EXPIRED_SESSION_STATE";
if (state == ZOO_AUTH_FAILED_STATE)return "AUTH_FAILED_STATE";
return "INVALID_STATE";
}
static const char* type2String(int state)
{if (state == ZOO_CREATED_EVENT)return "CREATED_EVENT";
if (state == ZOO_DELETED_EVENT)return "DELETED_EVENT";
if (state == ZOO_CHANGED_EVENT)return "CHANGED_EVENT";
if (state == ZOO_CHILD_EVENT)return "CHILD_EVENT";
if (state == ZOO_SESSION_EVENT)return "SESSION_EVENT";
if (state == ZOO_NOTWATCHING_EVENT)return "NOTWATCHING_EVENT";return "UNKNOWN_EVENT_TYPE";
}
void zktest_dump_stat(const struct Stat *stat)
{char tctimes[40];char tmtimes[40];
time_t tctime;
time_t tmtime;if (!stat)
{
fprintf(stderr,"null\n");
return;
}
tctime = stat->ctime/1000;
tmtime = stat->mtime/1000;
ctime_r(&tmtime, tmtimes);
ctime_r(&tctime, tctimes);
fprintf(stderr, "\tctime = %s\tczxid=%llx\n""\tmtime=%s\tmzxid=%llx\n""\tversion=%x\taversion=%x\n""\tephemeralOwner = %llx\n",
tctimes, stat->czxid,
tmtimes, stat->mzxid,
(unsigned int)stat->version, (unsigned int)stat->aversion,
stat->ephemeralOwner);
}
void zktest_data_completion(int rc, const char *value, int value_len, const struct Stat *stat, const void *data)
{
fprintf(stderr, "in data completion [%s]: rc = %d\n", value, rc);
zktest_dump_stat(stat);
}
/*process a list of string and stat*/void zktest_strings_stat_completion(int rc, const struct String_vector *strings, const struct Stat *stat, const void *data)
{int i=0;
fprintf(stderr, "in strings state completion [%s]: rc = %d, string count %d\n", (char *)data, rc, strings ->count);for (i=0; icount; i++) {
printf("%d: %s\n", i, strings->data[i]);
}
deallocate_String_vector(strings);
zktest_dump_stat(stat);
}void zktest_string_completion(int rc, const char *name, const void *data)
{
fprintf(stderr, "in string completion [%s]: rc = %d\n", (char*)(data==0?"null":data), rc);
if (!rc)
{
fprintf(stderr, "\tname = %s\n", name);
}
}void zktest_stat_completion(int rc, const struct Stat *stat, const void *data)
{if (rc == ZNONODE)
{
printf("node not exists\n");
}
fprintf(stderr, "in state completion rc = %d data=%s stat:\n", rc, (char *)data);
zktest_dump_stat(stat);
}void zktest_void_completion(int rc, const void *data) {
fprintf(stderr, "in void completion [%s]: rc = %d\n", (char*)(data==0?"null":data), rc);
}void zktest_watcher_g(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx) {
printf("Something happened.\n");
printf("type: %s\n", type2String(type));
printf("state: %s\n", state2String(state));
printf("path: %s\n", path);
printf("watcherCtx: %s\n", (char *)watcherCtx);int ret;const clientid_t *zk_clientid;if (path == NULL || strlen(path) == 0)
{
path="/xyz";
}if (type == ZOO_SESSION_EVENT) {if (state == ZOO_EXPIRED_SESSION_STATE) {
printf("[%s %d]zookeeper session expired\n", __FUNCTION__, __LINE__);
} else if (state == ZOO_CONNECTED_STATE) {
zk_clientid = zoo_client_id(zh);
printf("[%s %d] connected to zookeeper server with clientid=%lu\n", __FUNCTION__, __LINE__, zk_clientid ->client_id);if ((ret=zoo_aexists(zh, path, TRUE, zktest_stat_completion, path)) != ZOK)
{
printf("[%s %d] zoo_aexists judge error, msg = %s\n", __FUNCTION__, __LINE__, zerror(ret));
}if ((ret = zoo_aget(zh, (char *)path, TRUE, zktest_data_completion, "get param")) !=ZOK)
{
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}if ((ret = zoo_aget_children2(zh, path, TRUE, zktest_strings_stat_completion, "get children param")) !=ZOK)
{
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}
}
} else if (type == ZOO_CREATED_EVENT) {
printf("create a child node\n");if ((ret = zoo_aget_children2(zh, path, TRUE, zktest_strings_stat_completion, "get children param")) !=ZOK) {
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}if ((ret = zoo_aget(zh, path, TRUE, zktest_data_completion, "get param")) !=ZOK) {
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}
} else if (type == ZOO_DELETED_EVENT) {
printf("path %s deleted\n", path);if ((ret = zoo_aget(zh, path, TRUE, zktest_data_completion, "get param")) !=ZOK) {
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}
} else if (type == ZOO_CHANGED_EVENT) {
printf("path %s changed\n", path);if ((ret = zoo_aget_children2(zh, path, TRUE, zktest_strings_stat_completion, "get children param")) !=ZOK) {
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}if ((ret = zoo_aget(zh, path, TRUE, zktest_data_completion, "get param")) !=ZOK) {
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}
} else if (type == ZOO_CHILD_EVENT) {
printf("path %s child event\n");if ((ret = zoo_aget(zh, path, TRUE, zktest_data_completion, "get param")) !=ZOK) {
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}if ((ret = zoo_aget_children2(zh, path, TRUE, zktest_strings_stat_completion, "get children param")) !=ZOK) {
printf("[%s %d] fail to get znode %s, err=%d, msg= %s\n", __FUNCTION__, __LINE__, path, ret, zerror(ret));
}
}else if (type == ZOO_NOTWATCHING_EVENT){
}else {
printf("unkown zoo event type\n");
}
}int main(int argc, const char *argv[])
{static const char* host = "localhost:2181";int timeout = 30000;
zhandle_t* zkhandle;
zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
zoo_deterministic_conn_order(1);
zkhandle = zookeeper_init(host, zktest_watcher_g, 30000, 0, "hello world", 0);if (zkhandle == NULL) {
fprintf(stderr, "Error when connecting to zookeeper servers...\n");
exit(EXIT_FAILURE);
}/* Wait for asynchronous zookeeper call done.*/int fd, interest, events;int rc;
fd_set rfds, wfds, efds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);while(1){struct timeval tv;
zookeeper_interest(zkhandle, &fd, &interest, &tv);if (fd != -1) {if(interest&ZOOKEEPER_READ)
{
FD_SET(fd, &rfds);
} else {
FD_CLR(fd, &rfds);
}if(interest&ZOOKEEPER_WRITE)
{
FD_SET(fd, &wfds);
} else{
FD_CLR(fd, &wfds);
}
} else{
fd = 0;
}if (select(fd+1, &rfds, &wfds, &efds, &tv) < 0)
{
printf("[%s %d]select failed, err=%d, msg=%s\n", __FUNCTION__, __LINE__, errno, strerror(errno));
}
events = 0;if (FD_ISSET(fd, &rfds))
{
events |= ZOOKEEPER_READ;
}if (FD_ISSET(fd, &wfds))
{
events |= ZOOKEEPER_WRITE;
}
zookeeper_process(zkhandle, events);
}
zookeeper_close(zkhandle);
}
gcc -o zookeeper_s_test zookeeper_s_test.c -lzookeeper_st -I /usr/local/include/zookeeper/
執行結果:
|
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
|
2014-10-21 22:05:41,856:49845:ZOO_INFO@zookeeper_init@786: Initiating client connection, host=localhost:2181 sessionTimeout=30000 watcher=0x401444 sessionId=0 sessionPasswd=context=0x402213 flags=0
2014-10-21 22:05:41,859:49845:ZOO_INFO@check_events@1703: initiated connection to server [::1:2181]
2014-10-21 22:05:41,860:49845:ZOO_INFO@check_events@1750: session establishment complete on server [::1:2181], sessionId=0x14929440e3d0027, negotiated timeout=30000
2014-10-21 22:05:41,860:49845:ZOO_DEBUG@check_events@1756: Calling a watcher
for
a ZOO_SESSION_EVENT and the state=ZOO_CONNECTED_STATE
2014-10-21 22:05:41,860:49845:ZOO_DEBUG@process_completions@2107: Calling a watcher
for
node [], type = -1 event=ZOO_SESSION_EVENT
Something happened.
type: SESSION_EVENT
state: CONNECTED_STATE
path:
watcherCtx: hello world
[zktest_watcher_g 124] connected to zookeeper server with clientid=92650639611199527
2014-10-21 22:05:41,860:49845:ZOO_DEBUG@zoo_awexists@2835: Sending request xid=0x54473b25
for
path [/xyz] to ::1:2181
2014-10-21 22:05:41,860:49845:ZOO_DEBUG@zoo_awget@2655: Sending request xid=0x54473b26
for
path [/xyz] to ::1:2181
2014-10-21 22:05:41,860:49845:ZOO_DEBUG@zoo_awget_children2_@2916: Sending request xid=0x54473b27
for
path [/xyz] to ::1:2181
2014-10-21 22:05:41,862:49845:ZOO_DEBUG@zookeeper_process@2264: Queueing asynchronous response
2014-10-21 22:05:41,862:49845:ZOO_DEBUG@deserialize_response@2005: Calling COMPLETION_STAT
for
xid=0x54473b25 failed=0 rc=0
in state completion rc = 0 data=/xyz stat:
ctime
= Tue Oct 21 21:48:42 2014
czxid=400000052
mtime=Tue Oct 21 21:56:06 2014
mzxid=40000005a
version=2 aversion=0
ephemeralOwner = 0
2014-10-21 22:05:41,862:49845:ZOO_DEBUG@zookeeper_process@2264: Queueing asynchronous response
2014-10-21 22:05:41,862:49845:ZOO_DEBUG@deserialize_response@1992: Calling COMPLETION_DATA
for
xid=0x54473b26 failed=0 rc=0
in data completion [123]: rc = 0
ctime
= Tue Oct 21 21:48:42 2014
czxid=400000052
mtime=Tue Oct 21 21:56:06 2014
mzxid=40000005a
version=2 aversion=0
ephemeralOwner = 0
2014-10-21 22:05:41,862:49845:ZOO_DEBUG@zookeeper_process@2264: Queueing asynchronous response
2014-10-21 22:05:41,862:49845:ZOO_DEBUG@deserialize_response@2029: Calling COMPLETION_STRINGLIST_STAT
for
xid=0x54473b27 failed=0 rc=0
in strings state completion [get children param]: rc = 0, string count 0
ctime
= Tue Oct 21 21:48:42 2014
czxid=400000052
mtime=Tue Oct 21 21:56:06 2014
mzxid=40000005a
version=2 aversion=0
ephemeralOwner = 0
|
建議初學者使用時直接開debug,可以看清楚zookeeper的處理機制。
多線程庫使用示例。該程序自己創建,讀取,並刪除一個節點,並能夠觸發watcher。
#include
#include
#include
#include<zookeeper_log.h>
#include
#include
#include
#include
static const char* state2String(int state){
if (state == 0)
return "CLOSED_STATE";
if (state == ZOO_CONNECTING_STATE)
return "CONNECTING_STATE";
if (state == ZOO_ASSOCIATING_STATE)
return "ASSOCIATING_STATE";
if (state == ZOO_CONNECTED_STATE)
return "CONNECTED_STATE";
if (state == ZOO_EXPIRED_SESSION_STATE)
return "EXPIRED_SESSION_STATE";
if (state == ZOO_AUTH_FAILED_STATE)
return "AUTH_FAILED_STATE";
return "INVALID_STATE";
}
static const char* type2String(int state){
if (state == ZOO_CREATED_EVENT)
return "CREATED_EVENT";
if (state == ZOO_DELETED_EVENT)
return "DELETED_EVENT";
if (state == ZOO_CHANGED_EVENT)
return "CHANGED_EVENT";
if (state == ZOO_CHILD_EVENT)
return "CHILD_EVENT";
if (state == ZOO_SESSION_EVENT)
return "SESSION_EVENT";
if (state == ZOO_NOTWATCHING_EVENT)
return "NOTWATCHING_EVENT";
return "UNKNOWN_EVENT_TYPE";
}
void zookeeper_watcher_g(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx) {
printf("\nSomething happened.\n");
printf("type: %s\n", type2String(type));
printf("state: %s\n", state2String(state));
printf("path: %s\n", path);
printf("watcherCtx: %s\n", (char *)watcherCtx);
const clientid_t *zk_clientid;
int rc;
if (type == ZOO_CREATED_EVENT)
{
printf("[%s %d] znode %s created.\n", __FUNCTION__, __LINE__, path);
} else if (type == ZOO_DELETED_EVENT){
printf("[%s %d] znode %s deleted.\n", __FUNCTION__, __LINE__, path);
} else if (type == ZOO_CHANGED_EVENT){
printf("[%s %d] znode %s changed.\n", __FUNCTION__, __LINE__, path);
} else if(type == ZOO_CHILD_EVENT) {
printf("[%s %d] znode %s children changed.\n", __FUNCTION__, __LINE__, path);
} else if(type == ZOO_SESSION_EVENT) {
if(state == ZOO_EXPIRED_SESSION_STATE){
printf("[%s %d] zookeeper session expired\n", __FUNCTION__, __LINE__);
} else if (state == ZOO_AUTH_FAILED_STATE) {
printf("[%s %d] zookeeper session auth failed\n", __FUNCTION__, __LINE__);
} else if (state == ZOO_CONNECTING_STATE) {
printf("[%s %d] zookeeper session is connecting\n", __FUNCTION__, __LINE__);
} else if (state == ZOO_ASSOCIATING_STATE) {
printf("[%s %d] zookeeper session is associating state\n", __FUNCTION__, __LINE__);
} else if (state == ZOO_CONNECTED_STATE){
zk_clientid = zoo_client_id(zh);
printf("[%s %d] connected to zookeeper server with clientid=%lu\n", __FUNCTION__, __LINE__, zk_clientid ->client_id);
} else if (state == ZOO_NOTWATCHING_EVENT) {
printf("[%s %d] zookeeper session remove watch\n", __FUNCTION__, __LINE__);
} else {
printf("unknown session event state = %s, path = %s, ctxt=%s\n", state2String(state), path, (char *)watcherCtx);
}
}
}
void create(zhandle_t *zkhandle,char *str) {
char path_buffer[64]="abc";
int bufferlen=sizeof(path_buffer);
printf("create node in synchronous mode-----------------------\n");
int flag = zoo_create(zkhandle, str,"syn-node", 9,
&ZOO_OPEN_ACL_UNSAFE,0,
path_buffer,bufferlen);
if (flag!=ZOK) {
printf("create syn-node failed\n");
exit(EXIT_FAILURE);
} else {
printf("created node is %s\n",path_buffer);
}
}
void exists(zhandle_t *zkhandle,char *path)
{
int flag = zoo_exists(zkhandle, path, 1, NULL);
if (flag) {
printf("%s node already exist\n", path);
} else {
printf("%s node not exist\n", path);
}
}
void getACL(zhandle_t *zkhandle,char *str)
{
struct ACL_vector acl;
struct Stat stat;
int flag = zoo_get_acl(zkhandle,str,&acl,&stat);
if (flag==ZOK && acl.count > 0) {
printf("-----------------the ACL of %s:\n------------",str);
printf("%d\n",acl.count);
printf("%d\n",acl.data->perms);
printf("%s\n",acl.data->id.scheme);
printf("%s\n",acl.data->id.id);
}
}
void delete(zhandle_t *zkhandle,char *str)
{
int flag = zoo_delete(zkhandle,str,-1);
if (flag==ZOK) {
printf("delete node %s success\n", str);
}
}
int main(int argc, const char *argv[])
{
if (argc != 2) {
printf("usage: zookeeper_m_test server_address\n");
exit(-1);
}
const char* host = argv[1];
int timeout = 30000;
char buffer[512];
int *bufferlen;
zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
zhandle_t* zkhandle = zookeeper_init(host, zookeeper_watcher_g, timeout, 0, NULL, 0);
if (zkhandle ==NULL) {
fprintf(stderr, "Error when connecting to zookeeper servers...\n");
exit(EXIT_FAILURE);
}
create(zkhandle, "/abc");
exists(zkhandle, "/abc");
getACL(zkhandle, "/abc");
delete(zkhandle, "/abc");
while(1);
zookeeper_close(zkhandle);
}
cc -o zookeeper_m_test zookeeper_m_test.o -I/usr/local/include/zookeeper/ -L/usr/local/lib/ -L/usr/local/lib/x86_64-linux-gnu/ -lzookeeper_mt
執行:./zookeeper_m_test localhost:2181
|
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
|
2014-10-21 22:10:14,598:49903(0x7fc80aa16740):ZOO_INFO@zookeeper_init@786: Initiating client connection, host=localhost:2181 sessionTimeout=30000 watcher=0x400dfc sessionId=0 sessionPasswd=context=(nil) flags=0
2014-10-21 22:10:14,598:49903(0x7fc80aa16740):ZOO_DEBUG@start_threads@221: starting threads...
2014-10-21 22:10:14,599:49903(0x7fc8094c2700):ZOO_DEBUG@do_io@367: started IO
thread
2014-10-21 22:10:14,599:49903(0x7fc8094c2700):ZOO_INFO@check_events@1703: initiated connection to server [127.0.0.1:2181]
2014-10-21 22:10:14,599:49903(0x7fc808cc1700):ZOO_DEBUG@do_completion@459: started completion
thread
create node in synchronous mode-----------------------
2014-10-21 22:10:14,599:49903(0x7fc80aa16740):ZOO_DEBUG@zoo_acreate@2756: Sending request xid=0x54473c37
for
path [/abc] to 127.0.0.1:2181
2014-10-21 22:10:14,604:49903(0x7fc8094c2700):ZOO_INFO@check_events@1750: session establishment complete on server [127.0.0.1:2181], sessionId=0x14929440e3d0028, negotiated timeout=30000
2014-10-21 22:10:14,604:49903(0x7fc8094c2700):ZOO_DEBUG@check_events@1756: Calling a watcher
for
a ZOO_SESSION_EVENT and the state=ZOO_CONNECTED_STATE
2014-10-21 22:10:14,604:49903(0x7fc808cc1700):ZOO_DEBUG@process_completions@2107: Calling a watcher
for
node [], type = -1 event=ZOO_SESSION_EVENT
Something happened.
type: SESSION_EVENT
state: CONNECTED_STATE
path:
watcherCtx: (null)
[zookeeper_watcher_g 81] connected to zookeeper server with clientid=92650639611199528
2014-10-21 22:10:14,608:49903(0x7fc8094c2700):ZOO_DEBUG@process_sync_completion@1868: Processing sync_completion with type=6 xid=0x54473c37 rc=0
created node is /abc
2014-10-21 22:10:14,608:49903(0x7fc80aa16740):ZOO_DEBUG@zoo_awexists@2835: Sending request xid=0x54473c38
for
path [/abc] to 127.0.0.1:2181
2014-10-21 22:10:14,609:49903(0x7fc8094c2700):ZOO_DEBUG@process_sync_completion@1868: Processing sync_completion with type=1 xid=0x54473c38 rc=0
/abc node not exist
2014-10-21 22:10:14,609:49903(0x7fc80aa16740):ZOO_DEBUG@zoo_aget_acl@2989: Sending request xid=0x54473c39
for
path [/abc] to 127.0.0.1:2181
2014-10-21 22:10:14,611:49903(0x7fc8094c2700):ZOO_DEBUG@process_sync_completion@1868: Processing sync_completion with type=5 xid=0x54473c39 rc=0
-----------------the ACL of /abc:
------------1
31
world
anyone
2014-10-21 22:10:14,611:49903(0x7fc80aa16740):ZOO_DEBUG@zoo_adelete@2796: Sending request xid=0x54473c3a
for
path [/abc] to 127.0.0.1:2181
2014-10-21 22:10:14,613:49903(0x7fc8094c2700):ZOO_DEBUG@zookeeper_process@2193: Processing WATCHER_EVENT
2014-10-21 22:10:14,613:49903(0x7fc808cc1700):ZOO_DEBUG@process_completions@2107: Calling a watcher
for
node [/abc], type = -1 event=ZOO_DELETED_EVENT
Something happened.
type: DELETED_EVENT
state: CONNECTED_STATE
path: /abc
watcherCtx: (null)
[zookeeper_watcher_g 58] znode /abc deleted.
2014-10-21 22:10:14,613:49903(0x7fc8094c2700):ZOO_DEBUG@process_sync_completion@1868: Processing sync_completion with type=0 xid=0x54473c3a rc=0
delete
node /abc success
|
很明顯,多線程庫使用起來更方便。
更多API使用詳細可參考以下:
參考:
http://zookeeper.apache.org/doc/r3.4.6/zookeeperProgrammers.html#C+Binding
單線程與多線程的不同
你說的那些,都是多進程,你可以理解為一個應用程序(軟件)是一個進程,線程是在進程中的。一個進程可以有一個或多個線程,看起來就像某音頻播放軟件,一邊在顯示歌詞、一邊在顯示音頻柱、一邊在放歌。
單線程與多線程的優缺點是什
單線程就是進程只有一個線程
多線程就是進程有多個線程
多線程處理的優點
同步應用程序的開發比較容易,但由於需要在上一個任務完成后才能開始新的任務,所以其效率通常比多線程應用程序低。如果完成同步任務所用的時間比預計時間長,應用程序可能會不響應。多線程處理可以同時運行多個過程。例如,文字處理器應用程序在您處理文檔的同時,可以檢查拼寫(作為單獨的任務)。由於多線程應用程序將程序划分成獨立的任務,因此可以在以下方面顯著提高性能:
多線程技術使程序的響應速度更快,因為用戶界面可以在進行其他工作的同時一直處於活動狀態。
當前沒有進行處理的任務可以將處理器時間讓給其他任務。
占用大量處理時間的任務可以定期將處理器時間讓給其他任務。
可以隨時停止任務。
可以分別設置各個任務的優先級以優化性能。
是否需要創建多線程應用程序取決於多個因素。在以下情況下,最適合采用多線程處理:
耗時或大量占用處理器的任務阻塞用戶界面操作。
各個任務必須等待外部資源(如遠程文件或 Internet 連接)。
例如,用於跟蹤 Web 頁上的鏈接並下載滿足特定條件的文件的 Internet 應用程序“robot”。這種應用程序可以依次同步下載各個文件,也可以使用多線程同時下載多個文件。多線程方法比同步方法的效率高很多,因為即使在某些線程中遠程 Web 服務器的響應非常慢,也可以下載文件。
cache.baidu.com/...aidu#0
下面是多線程的例子
還在Dos時代,人們就在尋求一種多任務的實現。於是出現了TSR類型的后台駐留程序,比較有代表性的有Side Kick、Vsafe等優秀的TSR程序,這類程序的出現和應用確實給用戶使用計算機帶來了極大的方便,比如Side Kick,我們編程可以在不用進編輯程序的狀態下,一邊編輯源程序,一邊編譯運行,非常方便。但是,Dos單任務操作系統的致命缺陷注定了在Dos下不可能開發出真正的多任務程序。進入Windows3.1時代,這種情況依然沒有根本的改變,一次應用只能做一件事。比如數據庫查詢,除非應用編得很好,在查詢期間整個系統將不響應用戶的輸入。
進入了Windows NT和Windows 9x時代,情況就有了徹底的改觀,操作系統從真正意義上實現了多任務(嚴格地說,Win9x還算不上)。一個應用程序,在需要的時候可以有許多個執行線程,每個線程就是一個小的執行程序,操作系統自動使各個線程共享CPU資源,確保任一線程都不能使系統死鎖。這樣,在編程的時候,可以把費時間的任務移到后台,在前台用另一個線程接受用戶的輸入。對那些對實時性要求比較高的編程任務,如網絡客戶服務、串行通信等應用時,多線程的實現無疑大大地增強了程序的可用性和穩固性。
