准备知识:
1、了解THREADED(多线程)下c client运行的架构:
在多线程下,用户每次调用zookeeper_init生成一个zhandle_t结构都会生成除了调用线程外的另两线程:do_io线程和do_completion线程。
- do_completion:
主要内容是执行异步完成回调函数和watcher事件通知函数,代码比较简单,主要处理zk->completions_to_process队列。
| #ifdef WIN32 |
| unsigned __stdcall do_completion( void * v) |
| #else |
| void *do_completion(void *v) |
| #endif |
| { |
| zhandle_t *zh = v; |
| api_prolog(zh); |
| notify_thread_ready(zh); |
| LOG_DEBUG(LOGCALLBACK(zh), "started completion thread"); |
| while(!zh->close_requested) { |
| pthread_mutex_lock(&zh->completions_to_process.lock); |
| while(!zh->completions_to_process.head && !zh->close_requested) { |
| pthread_cond_wait(&zh->completions_to_process.cond, &zh->completions_to_process.lock); |
| } |
| pthread_mutex_unlock(&zh->completions_to_process.lock); |
| process_completions(zh); |
| } |
| api_epilog(zh, 0); |
| LOG_DEBUG(LOGCALLBACK(zh), "completion thread terminated"); |
| return 0; |
| } |
- do_io:
该线程是核心线程,主要通过poll来异步处理与zookeeper server之间的通信。核心架构如下:
| void *do_io(void *v) |
| |
| { |
| zhandle_t *zh = (zhandle_t*)v; |
| |
| struct pollfd fds[2]; |
| struct adaptor_threads *adaptor_threads = zh->adaptor_priv; |
| api_prolog(zh); |
| notify_thread_ready(zh); |
| LOG_DEBUG(LOGCALLBACK(zh), "started IO thread"); |
| fds[0].fd=adaptor_threads->self_pipe[0]; // 在poll中注册self_pipe[0],用于激活或通知do_io线程。 |
| fds[0].events=POLLIN; |
|
while(!zh->close_requested)
{
//while循环,直到调用zookeeper_close,使close_requested为真。
|
| zh->io_count++; |
| struct timeval tv; |
| int fd; |
| int interest; |
| int timeout; |
| int maxfd=1; |
| int rc; |
| zookeeper_interest(zh, &fd, &interest, &tv); //zookeeper_interest,判断zh->fd是否为-1(连接到server的socket fd)。 如果为-1,选择当前connect_index,对应的server进行连接。connect_index的修改是在handler_error里面搞的,round-robin。具体请参考:http://hi.baidu.com/anatacollin/item/fc9ccfb4dcedb8f363388e11 |
|
if (fd != -
1)
{
|
| fds[1].fd=fd; |
| fds[1].events=(interest&ZOOKEEPER_READ)?POLLIN:0; |
| fds[1].events|=(interest&ZOOKEEPER_WRITE)?POLLOUT:0; |
| maxfd=2; |
| } |
| timeout=tv.tv_sec * 1000 + (tv.tv_usec/1000); |
| poll(fds,maxfd,timeout); |
| if (fd != -1) { |
| interest=(fds[1].revents&POLLIN)?ZOOKEEPER_READ:0; |
| interest|=((fds[ |

本文深入剖析Zookeeper C客户端的源码,重点关注do_completion和do_io两个关键函数,揭示不同事件触发的条件与时机,特别是异步操作的实现细节和线程交互机制。
最低0.47元/天 解锁文章
561

被折叠的 条评论
为什么被折叠?



