zookeeper的c API 单线程与多线程问题 cli_st和cli_mt
同样的程序,在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资源,确保任一线程都不能使系统死锁。这样,在编程的时候,可以把费时间的任务移到后台,在前台用另一个线程接受用户的输入。对那些对实时性要求比较高的编程任务,如网络客户服务、串行通信等应用时,多线程的实现无疑大大地增强了程序的可用性和稳固性。
zookeeper的c API 单线程与多线程问题 cli_st和cli_mt的更多相关文章
- JavaScript是单线程还是多线程(转)
多线程要考虑线程之间的资源抢占,死锁,冲突之类一系列问题.JavaScript作为一门客户端脚本,貌似没有多线程的一些列问题.那么JavaScript是单线程还是多线程?通过查资料总结了JavaScr ...
- java归并排序,单线程vs多线程
一.什么是归并排序 归并排序又称合并排序,它是成功应用分治技术的一个完美例子.对于一个需要排序的数组A[0..n-1],归并排序把它一分为二:A[0..n/2-1]和A[n/2..n-1],并对每个子 ...
- python单线程,多线程和协程速度对比
在某些应用场景下,想要提高python的并发能力,可以使用多线程,或者协程.比如网络爬虫,数据库操作等一些IO密集型的操作.下面对比python单线程,多线程和协程在网络爬虫场景下的速度. 一,单线程 ...
- Python-爬取校花网视频(单线程和多线程版本)
一.参考文章 python爬虫爬取校花网视频,单线程爬取 爬虫----爬取校花网视频,包含多线程版本 上述两篇文章都是对校花网视频的爬取,由于时间相隔很久了,校花网上的一些视频已经不存在了,因此上述文 ...
- Python-爬取妹子图(单线程和多线程版本)
一.参考文章 Python爬虫之——爬取妹子图片 上述文章中的代码讲述的非常清楚,我的基本能思路也是这样,本篇文章中的代码仅仅做了一些异常处理和一些日志显示优化工作,写此文章主要是当做笔记,方便以后查 ...
- Linux -- 基于zookeeper的java api(二)
Linux -- 基于zookeeper的java api(二) 写一个关于基于集群的zookeeper的自定义实现HA 基于客户端和监控器:使用监控的方法查看每个注册过的节点的状态来做出操作. Wa ...
- Linux -- 基于zookeeper的java api(一)
Linux -- 基于zookeeper的java api 首先启动你所有的 zkService.sh 查看状态:检查是否启动正确 [root@hu-hadoop2 ~]# zkServer.sh s ...
- ZooKeeper客户端原生API的使用以及ZkClient第三方API的使用
这两部分内容的介绍主要讲的是节点及节点内容和子节点的操作,并且讲解的节点的事件监听以及ACL授权 ZooKeeper客户端原生API的使用 百度网盘地址: http://pan.baidu.com/s ...
- 面试之二:Redis是单线程还是多线程?以及处理模型。
Redis是单线程还是多线程?以及处理模型. 线程:单线程 处理模型:参考书<Redis 设计与实现>P151-152 ![](https://ws1.sinaimg.cn/large ...
随机推荐
- [Face++]Face初探——人脸检测
经过了强烈的思想斗争才把自己拖到图书馆做毕设T^T anyway, 因为毕设里面有人脸识别的部分,所以就想找个现成的api先玩玩,于是就找到最近很火的face++:http://www.faceplu ...
- 照着官网来安装openstack pike之keystone安装
openstack基础环境安装完成后,现在开启安装keystone服务(在控制节点上执行下面所有操作) 1.为keystone创建数据库 mysql -u root -p MariaDB [(none ...
- 组播的介绍以及CS模型实现
1.组播介绍 组播组可以是永久的也可以是临时的.组播组地址中,有一部分由官方分配的,称为永久组播组. 永久组播组保持不变的是它的ip地址,组中的成员构成可以发生变化.永久组播组中成员的数量都可以是任意 ...
- 输入n,求1~n累加
最开始可能会使用for循环来计算,现在直接使用等差数据计算和公式:s=(a0+n)*n/2 long sum(int n) { long ret=0: ret = (1+n)* n /2: retur ...
- 【前端】Vue.js实现简单价格计算器
价格计算器 实现效果: 实现代码及注释: <!DOCTYPE html> <html> <head> <title>价格计算器</title> ...
- Ansible Playbooks入门介绍
1.目录结构 2.详细目录 3.主任务文件main.yaml 主任务文件main.yaml - name: print server name and user to remote testbox # ...
- SpringMVC两种处理器适配器
1.实现Controller接口的处理器适配器 package com.xiaostudy; import javax.servlet.http.HttpServletRequest; import ...
- codeforces 1A - math - ceil
2017-08-24 15:42:30 writer: pprp 感觉自己好菜啊,这个题都没有做的很好 题意很简单,用a * a 的地砖,将 n * m 的地板铺满,问最少需要多少个地砖? 一开始打算 ...
- Android -- ContentObserver 内容观察者
1. 实现原理图 2. 示例代码 (暂时有个问题,短信观察者 收到一条短信时 onchange方法会执行两次, 解决方法为:每次监听到变化的时候就去取最新短信的id,跟上次取的比较,如果一样的就不做处 ...
- Struts 2 + Hibernate + Spring 整合要点
Struts 2 和 Spring 的功能有重合,因此有必要说明下,整合中分别使用了两种框架的哪些技术. Struts 2 使用功能点: 1.拦截器.一处是对非登录用户购物进行拦截,一处是对文件上传的 ...