本文档的Copyleft归L.L所有,使用GPL发布,可以自由转载,转载时请务必以超链接形式标明文章原始出处,严禁用于任何商业用途。
email: [email protected]
来源: http://blog.csdn.net/ccdd14
前面把初始化流程分析完成,可以发现,nginx是先把各模块的指令初始化完成后,再初始化子进程,最后等待客户请求到来。下面开始分析nginx的处理流程。
ngx_event_accept是整个处理流程的开始,它调用accept等待连接的到来,当有新连接到来时,通过ngx_get_connection取得一个空闲连接,注册连接的发送接收钩子(还记得第一章的ngx_linux_io ?):
//这里的recv是ngx_unix_recv c->recv = ngx_recv; //这里的send是ngx_unix_send c->send = ngx_send; //这里的recv_chain是ngx_readv_chain c->recv_chain = ngx_recv_chain; //这里的send_chain 是ngx_linux_sendfile_chain c->send_chain = ngx_send_chain;
然后将该连接添加到epoll事件中,触发ngx_listening_t的handler:ngx_http_init_connection,分析一下这个函数:
void ngx_http_init_connection(ngx_connection_t *c) { ngx_event_t *rev; ngx_http_log_ctx_t *ctx; ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); if (ctx == NULL) { ngx_http_close_connection(c); return; } //初始化ngx_http_log_ctx_t ctx->connection = c; ctx->request = NULL; ctx->current_request = NULL; //初始化连接的log c->log->connection = c->number; c->log->handler = ngx_http_log_error; c->log->data = ctx; c->log->action = "reading client request line"; c->log_error = NGX_ERROR_INFO; rev = c->read; //注册读写事件的handler,当事件到来时,epoll就触发它 rev->handler = ngx_http_init_request; c->write->handler = ngx_http_empty_handler; #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); #endif if (rev->ready) { /* the deferred accept(), rtsig, aio, iocp */ if (ngx_use_accept_mutex) { //添加读事件到ngx_posted_events队列中 ngx_post_event(rev, &ngx_posted_events); return; } ngx_http_init_request(rev); return; } //添加到定时器ngx_event_timer_rbtree中,c->listening->post_accept_timeout=60s ngx_add_timer(rev, c->listening->post_accept_timeout); //把事件添加到合适的事件模型中,linux中是epoll if (ngx_handle_read_event(rev, 0) != NGX_OK) { #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); #endif ngx_http_close_connection(c); return; } }
当连接的数据到来时,就接着调用ngx_http_init_request。
ngx_http_init_request函数初始化ngx_http_request_t结构,注册了几个handler:rev->handler = ngx_http_process_request_line,r->read_event_handler = ngx_http_block_reading,r->log_handler = ngx_http_log_error_handler,设置了http状态r->http_state = NGX_HTTP_READING_REQUEST_STATE,这是一系列枚举值:
typedef enum { NGX_HTTP_INITING_REQUEST_STATE = 0, NGX_HTTP_READING_REQUEST_STATE, NGX_HTTP_PROCESS_REQUEST_STATE, NGX_HTTP_CONNECT_UPSTREAM_STATE, NGX_HTTP_WRITING_UPSTREAM_STATE, NGX_HTTP_READING_UPSTREAM_STATE, NGX_HTTP_WRITING_REQUEST_STATE, NGX_HTTP_LINGERING_CLOSE_STATE, NGX_HTTP_KEEPALIVE_STATE } ngx_http_state_e;
最后调用ngx_http_process_request_line。
ngx_http_process_request_line函数首先调用ngx_http_read_request_header接收数据,数据保存在r->header_in缓冲区中。接着利用ngx_http_parse_request_line解析http request-line(如:GET / HTTP/1.1),如果解析没有发生错误,重新注册rev->handler = ngx_http_process_request_headers,调用ngx_http_process_request_headers。
ngx_http_process_request_headers函数使用ngx_http_parse_header_line解析head field,然后查找hash得到hh(类型为ngx_http_header_t),接着调用hh注册的handler,这些handler在ngx_http_headers_in变量里注册。
//位于ngx_http_request.c ngx_http_header_t ngx_http_headers_in[] = { { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host), ngx_http_process_host }, { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection), ngx_http_process_connection }, { ngx_string("If-Modified-Since"), offsetof(ngx_http_headers_in_t, if_modified_since), ngx_http_process_unique_header_line }, { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent), ngx_http_process_user_agent }, { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer), ngx_http_process_header_line }, { ngx_string("Content-Length"), offsetof(ngx_http_headers_in_t, content_length), ngx_http_process_unique_header_line }, { ngx_string("Content-Type"), offsetof(ngx_http_headers_in_t, content_type), ngx_http_process_header_line }, { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range), ngx_http_process_header_line }, { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range), ngx_http_process_unique_header_line }, ................................... ....................................
得到head field的(key,value)值对后,改变状态r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE,调用ngx_http_process_request_header分析head field的合法性,最后调用ngx_http_process_request。
ngx_http_process_request函数又注册了几个handler:c->read->handler = ngx_http_request_handler,c->write->handler = ngx_http_request_handler,r->read_event_handler = ngx_http_block_reading。紧接着调用ngx_http_handler,这个函数做了一件非常重要的事情,运行各http phase注册的handler。
这涉及一大串的handler,下一章再慢慢吃了。