Memcached源码分析--线程模型(一)
原文:http://www.iteye.com/topic/344172下面对memcached的线程模型做下简单分析,先看下memcahced启动时线程处理的流程。
http://blog.运维网.com/attachment/201201/134320242.jpg
memcached的多线程主要是通过实例化多个libevent实现的,分别是一个主线程和n个workers线程
无论是主线程还是workers线程全部通过libevent管理网络事件,实际上每个线程都是一个单独的libevent实例
主线程负责监听客户端的建立连接请求,以及accept 连接
workers线程负责处理已经建立好的连接的读写等事件
先看一下大致的图示:
http://blog.运维网.com/attachment/201201/134348792.jpg
首先看下主要的数据结构(thread.c):
[*]/* An item in the connection queue. */
[*]typedef struct conn_queue_item CQ_ITEM;
[*]struct conn_queue_item {
[*] int sfd;
[*] int init_state;
[*] int event_flags;
[*] int read_buffer_size;
[*] int is_udp;
[*] CQ_ITEM *next;
[*]};
CQ_ITEM 实际上是主线程accept后返回的已建立连接的fd的封装
[*]/* A connection queue. */
[*]typedef struct conn_queue CQ;
[*]struct conn_queue {
[*] CQ_ITEM *head;
[*] CQ_ITEM *tail;
[*] pthread_mutex_t lock;
[*] pthread_cond_tcond;
[*]};
CQ是一个管理CQ_ITEM的单向链表
[*]typedef struct {
[*] pthread_t thread_id; /* unique ID of this thread */
[*] struct event_base *base; /* libevent handle this thread uses */
[*] struct event notify_event;/* listen event for notify pipe */
[*] int notify_receive_fd; /* receiving end of notify pipe */
[*] int notify_send_fd; /* sending end of notify pipe */
[*] CQnew_conn_queue; /* queue of new connections to handle */
[*]} LIBEVENT_THREAD;
这是memcached里的线程结构的封装,可以看到每个线程都包含一个CQ队列,一条通知管道pipe 和一个libevent的实例event_base
另外一个重要的最重要的结构是对每个网络连接的封装conn
[*]typedef struct{
[*]int sfd;
[*]int state;
[*]struct event event;
[*]short which;
[*]char *rbuf;
[*]... //这里省去了很多状态标志和读写buf信息等
[*]}conn;
memcached主要通过设置/转换连接的不同状态,来处理事件(核心函数是drive_machine)
下面看下线程的初始化流程:
在memcached.c的main函数中,首先对主线程的libevent做了初始化
[*]/* initialize main thread libevent instance */
[*] main_base = event_init();
然后初始化所有的workers线程,并启动,启动过程细节在后面会有描述
[*]/* start up worker threads if MT mode */
[*]thread_init(settings.num_threads, main_base);
接着主线程调用(这里只分析tcp的情况,目前memcached支持udp方式)
[*]server_socket(settings.port, 0)
这个方法主要是封装了创建监听socket,绑定地址,设置非阻塞模式并注册监听socket的
libevent 读事件等一系列操作
然后主线程调用
[*]/* enter the event loop */
[*]event_base_loop(main_base, 0);
这时主线程启动开始通过libevent来接受外部连接请求,整个启动过程完毕。
Memcached源码分析--线程模型(二)
Memcached源码分析--线程模型(三)
页:
[1]