memcached 网络模型
多线程
memcached包含一个main线程,和若干个worker子线程。main线程负责监听创建客户端连接。worker线程负责处理各个客户端的请求。
memcached启动时,main线程创建了一个listen_fd负责监听端口,worker线程监听管道状态。
(1)一旦有客户端连接(图中蓝箭头1),Event_handler响应函数触发
(2)event_handler会向某一个worker线程的管道写数据(箭头2),这会触发线程的管道响应函数thread_libevent_process。
(3) thread_libevent_process函数会接受client_fd, 放入其线程队列中,并设置其对应的事件函数eventhandler(箭头3)。
(4)客户端发送set,get等命令(箭头4),event_handler函数被触发,调用具体命令的处理方法。
(5)处理后,返回结果(箭头5)
一个比喻:
main线程就类似于10086的接线员,worker线程是具体的业务员。用户拨打10086(步骤1),接线员(main)通知具体的业务员(步骤2),业务员接起电话(步骤3),接下来的步骤,用户可以和业务员直通,步骤4和步骤5
伪代码的调用关系图如下:
main(){
xxx_init() 一系列初始化函数
memcached_thread_init(){
for each thread(){
setup_thread() {
event_set(notify,) // 响应函数 thread_libevent_process
cq_init()
cache_create()
}
create_worker(){
new thread with func worker_libevent() {
event_base_loop() // 每个线程进入循环
}
}
}
}
init_lru_crawler()
clock_handler()
server_sockets(){
server_socket(){
bind()
listen()
conn_new(){ // accept是面向多客户端的,需要放到event里处理
event_set() // 连接事件,响应函数 event_handler
}
}
}
event_base_loop()
}
event_handler(){ //主线程和worker线程响应函数
drive_machine(){
case: new_listening
dispatch_conn_new(){
notify worker thread;
push CQ_ITEM to queue;
}
case
}
}
thread_libevent_process(){ // 管道fd的响应函数
switch(){
case c 新连接
conn_new() { event_set()}
conn_worker_readd(){
event_set()
}
case p
case t
case s
}
}
上述代码,注意conn函数的特点,在main和worker中都有被调用, 给main和worker注册事件响应函数。
来源 https://www.modb.pro/db/103311
相关文章