每个zookeeper API必须有一个zhandle。当初始化一个zhandle时(zookeeper_init)首先初始化zhandle的相应字段然后创建两个线程:do_io,do_completion;并且等待这两个线程初始化完成后才返回,这两个线程也要等待彼此初始化完成后,才提供服务(notify_thread_ready)。
1 IO线程/do_io
显然这个线程用于处理io请求(使用Poll多路复用方式),这里的io请求就是与zookeeper server的网络io处理(zh->fd)。除了这个io外,该线程还关注一个管道的读取端的io(adaptor_threads->self_pipe[0]),该io的唯一作用就是唤醒该线程,即其它线程通过向adaptor_threads->self_pipe[1]写一个字符来唤醒该线程(wakeup_io_thread)。对于第一种io,需要确定所关注的event,以及等待的时间(zookeeper_interest);然后进入poll等待事件可用;当poll返回后先确定哪些事件可用了;清空adaptor_threads->self_pipe[0];最后调用zookeeper_process处理可用事件,如对于同步请求的响应则直接在这个线程里把结果保存到应用的buf,并唤醒应用,对于异步请求则把sent_requests的completion对象放入completions_to_process队列让completion线程来处理。
2 completion线程/do_completion
该线程负责从completions_to_process取出completion来处理,这个处理包括对completion回调及watch回调的处理。处理的函数为process_completions。
3 API
Zookeeper的API可以分成三类,如我们以get为例:zoo_get、zoo_wget、zoo_awget。其中’w’表示是否自己指定watch回调函数,如果指定的话需要传入watch 回调函数及context参数,’a’表示异步方式,需要指定completion回调函数及它的data参数,并且这个这个回调函数由completion线程调用(非a表示同步方式,即等待请求从服务返回后才返回给应用,这期间应用阻塞等待)。对于内部实现来说get及wget都是通