memcached之网络处理流程之conn_new_cmd

来源:互联网 发布:17173魔兽数据库 编辑:程序博客网 时间:2024/04/28 17:52

memcached主要通过设置/转换连接的不同状态,来处理事件.


static int server_socket(int port, enum network_transport transport,FILE *portnumber_file) {
listen_conn_add = conn_new(sfd, conn_listening, EV_READ | EV_PERSIST, 1, transport, main_base));
}


假如主线程使用的是tcp协议,则调用server_socket函数,该函数创建socket并绑定端口.最重要的处理就是conn_new函数,核心的参数是conn_listening(这个是主线程才会处理的).conn_new函数又创建一个event事件,假如有链接过来就回调drive_machine核心函数

 


case conn_listening:
sfd = accept(c->sfd, (struct sockaddr *)&addr, &addrlen);
dispatch_conn_new(sfd, conn_new_cmd, EV_READ | EV_PERSIST, DATA_BUFFER_SIZE, tcp_transport);


主线程触发accept事件后,就将其分发到worker线程中,注意这个时候链接的状态变成了conn_new_cmd.


void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags,int read_buffer_size, enum network_transport transport) {
    CQ_ITEM *item = cqi_new();
    int tid = (last_thread + 1) % settings.num_threads;
    LIBEVENT_THREAD *thread = threads + tid;
    last_thread = tid;
    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;
    cq_push(thread->new_conn_queue, item);
    if (write(thread->notify_send_fd, "", 1) != 1) {
        perror("Writing to thread notify pipe");
    }
}


这里有几点注意的地方:
(1)创建一个cq_item对象,包含init_state参数为conn_new_cmd.并将其放入到对应worker线程的链接队列里面


(2)通过write系统函数更新对应线程的管道的写端


(3)IBEVENT_THREAD *thread = threads + tid  表现形式可以细细体会


case conn_new_cmd:
if (nreqs >= 0) {
         reset_cmd_handler(c);
}


worker线程触发时间后回调thread_libevent_process函数,该函数读出一个字节后,从该线程队列里取出一个cq_item,调用conn_new函数创建conn对象.从而进入
conn_new_cmd处理逻辑.


假如发现连接符中有数据则跳转到conn_parse_cmd.否则处于等待具体的代码:
if (c->rbytes > 0) {
     conn_set_state(c, conn_parse_cmd);
} else {
     conn_set_state(c, conn_waiting);
}


case conn_parse_cmd :
if (try_read_command(c) == 0) {
      conn_set_state(c, conn_waiting);
}


解析命令成功后,则跳转到conn_waitting过程
update_event(c, EV_READ | EV_PERSIST),最后跳转到conn_read处理流程

原创粉丝点击