Chinaunix首页 | 论坛 | 博客
  • 博客访问: 550621
  • 博文数量: 469
  • 博客积分: 50
  • 博客等级: 民兵
  • 技术积分: 1495
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-15 21:04
文章分类

全部博文(469)

文章存档

2015年(81)

2014年(125)

2013年(261)

2012年(2)

分类: LINUX

2013-08-27 11:46:42

原文地址:memcached分析--主架构解析 作者:zghover

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) |
给主人留下些什么吧!~~