memcached是利用libevent实现的一个高性能K/V缓存系统。最近研究了它的源码,写一下心得。
一,简介
该系统是利用libevent时间驱动库实现的一个多线程K/V缓存系统,支持TCP和UDP。
可以大概把线程分为两种,一种是分发线程(主线程),一种是worker线程,也就是进行后续命令处理的线程。
1, 首先创建worker线程,创建worker线程时,完成以下工作:
(1) 为每个线程创建一个管道(pipe)
(2) 把管道的接受端描述符notify_receive_fd添加到进libevent事件队列中
(3) 注册事件处理函数thread_libevent_process
(4) 为每个线程创建连接队列new_conn_queue
2, 主线程创建主监听socket,并把该socket加入到libevent事件队列中,当有连接请求到来时调用dispatch_conn_new,完成以下事项:
(1) 创建新的item,这个Item包括了本次连接的信息:cfg,readbufersize等
(2) 把该item添加到该线程的
new_conn_queue队列中。
(3) 轮询选择一个worker线程,并向该worker线程的管道的写端描述符:notify_send_fd 写入命令'c',表示有新的连接到来。
3, 当worker线程接受到'c'命令时,会调用
thread_libevent_process函数处理读事件,注意此时item中的状态是conn_new_cmd
4,
thread_libevent_process函数的处理流程如下:
(1) 从new_conn_queue队列中取出一个item
(2) 从连接队列中取一个新的连接结构,并把该本次的item中的cfd添加到事件队列中,注册事件函数event_handler->driver_machine()函数进行后续命令处理。 其中Item的状态是conn_new_cmd。
5, 调用driver_machine进行处理。
简要流程图如下:
通讯pipe (有连接请求时发送'c'命令)
| | ==================== | worker thread1 |
|main thread | ==================== | worker thread2 |
| | ==================== | worker threadn | -最终进入--->driver_machine()
\ /\
\ connect request /
push \ / pull (从事件队列中取事件时要加锁)
\/ /
[req1]->[req2]->[req3]->...[req4]->[reqn] 事件队列event queue
二,源码简析
* 流程解析
主函数中的函数调用关系如下:
main()
->thread_init()
->server_sockets()
->server_socket()
->conn_new()
设计一个服务器一般都是从建立socket开始的,所以这里从建立监听socket开始讲解:
(1) 在主线程中,调用函数server_sockets()建立主监听socket描述符,若有多个地址的话,会在多个ip地址进行监听,多个地址之间用,分开。
(2) server_sockets()函数主要完成主socket的建立,并把该socket描述符添加到libeven事件监控队列中,该socket的事件处理函数是event_handler。
(3) 初始化状态时conn_listening,当有连接到来时,进入函数event_handler函数进行处理。
(4) event_handler函数调用drive_machine状态处理函数进行处理。
(5) 初始化状态是conn_listening,但有连接请求时调用dispatch_conn_new函数。
(6) dispatch_conn_new函数,从work_thread中找一个线程,并向该线程的管道(管道写描述符notify_send_fd)写入一个命令'c',表示要新创建一个连接。
(7) work 线程thread_libevent_process函数进行事件处理,收到该命令后,会创建一个新的连接,并从item队列中取一个item。最终进入到driver_machine事件驱动函数,接受各种get,set命令。
小结:这种框架可以认为是一种经典的单writer和多reader框架。
阅读(373) | 评论(0) | 转发(0) |