nginx源码分析——http处理流程
博客专区 > hncscwc 的博客 > 博客详情
nginx源码分析——http处理流程
hncscwc 发表于1年前
nginx源码分析——http处理流程
  • 发表于 1年前
  • 阅读 266
  • 收藏 6
  • 点赞 0
  • 评论 2

腾讯云 新注册用户 域名抢购1元起>>>   

1. http处理流程概述

nginx对于http请求处理的大概流程是:接收客户端发起的连接,然后接收并解析http请求行,接收并解析http头部;再根据配置文件nginx.conf找到相关http模块,使这些模块依次合作处理http请求,最后发送http响应并结束http请求。

在整个http请求处理过程中,nginx通过连接的读写事件,以及定时器机制,异步回调完成其处理流程。

2. http新连接的建立

事件模块一文中我们知道,当新连接建立后会回调对应侦听的处理方法。对于http模块,该回调方法为ngx_http_init_connection。在该方法中,主要完成的事情是:设置连接的读事件回调处理方法为ngx_http_wait_request_handler,设置连接的写事件回调处理方法为ngx_http_empty_handler;然后查看读事件是否已经准备好,即连接对应的套接字缓冲区上是否已经接收到用户的请求数据了,如果是,则直接调用ngx_http_wait_request_handler进入下一处理步骤;如果还没有准备好,则对连接的读事件设置定时器,同时将读事件添加到事件驱动中,等待下一次回调处理。

void ngx_http_init_connection(ngx_connection_t *c)
{
    ...
    // 设置读写事件回调处理方法
    rev = c->read;
    rev->handler = ngx_http_wait_request_handler;
    c->write->handler = ngx_http_empty_handler;

    if( rev->ready ) {
        if( ngx_use_accept_mutex ) {
            ngx_post_event(rev, &ngx_posted_events);
            return;
        }
        // 事件已经准备好, 直接处理
        rev->handler(rev);
        return;
    }

    // 设置定时器
    ngx_add_timer(rev, c->listening->post_accept_timeout);
    ngx_reusable_connection(c, 1);

    // 将读事件加入事件驱动中
    if(ngx_handle_read_event(rev, 0) != NGX_OK) {
        ngx_http_close_connection(c);
        return;
    }
}

3. 首次可读事件的处理

当连接对应的套接字缓冲区首次接收到用户的请求数据后,会回调ngx_http_wait_request_handler方法,在该函数中,会调用recv接收用户的请求数据,同时创建一个ngx_http_request_t用于本次http请求处理,然后调用ngx_http_process_request_line开始处理http请求行。

static void ngx_http_wait_request_handler(ngx_event_t *rev)
{
    ....
    // 接收数据
    n = c->recv(c, b->last, size);
    if( n == NGX_AGAIN ) {
        if(!rev->timer_set) {
            ngx_add_timer(rev, c->listening->post_accept_timeout);
            ngx_reusable_connection(c, 1);
        }
        if( ngx_handle_read_event(rev,0) != NGX_OK ) {
            ngx_http_close_connection(c);
            return ;
        }
    }
    if(n == NGX_ERROR ) {
        ngx_http_close_connection(c);
        return ;
    }

    ....
    
    // 创建request
    c->data = ngx_http_create_request(c);
    if(c->data == NULL) {
        ngx_http_close_connection(c);
        return ;
    }
    rev->handler = ngx_http_process_request_line;
    ngx_http_post_request_line(rev);
}

4. http请求行/http头部的接收处理

在完成了请求的初始化后,会依次调用ngx_http_process_request_line和ngx_http_process_request_headers方法开始接收http请求行和http头部,并解析出URL,请求方法等各字段的含义。当这些都处理完成后,调用ngx_http_process_request进入请求真正的处理阶段。

static void ngx_http_process_request_line(ngx_event_t * rev)
{
    ....
    for( ;; ) {
        // 解析 http行
        rc = ngx_http_parse_request_line(r, r->header_in);
        if( rc == NGX_OK ) {
            // 处理http uri
            if(ngx_http_process_request_uri(r) != NGX_OK) {
                return ;
            }

            // 设置连接的读事件回调处理, 并开始处理http请求的头部
            rev->handler = ngx_http_process_request_headers;
            ngx_http_process_request_headers(rev);
            return ;
        }
    }
}

static void ngx_http_process_request_headers(ngx_event_t * rev)
{
    ....
    rc = NGX_AGAIN;
    for( ;; ) {
        if( rc == NGX_AGAIN ) {
            n = ngx_http_request_header(r);
        }

        // 解析http的头部
        rc = ngx_http_parse_header_line(r, r->header_in, cscf->underscores_in_headers);
        if( rc == NGX_HTTP_PARSE_HEADER_DONE) {
            r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
            // 处理http的头部
            rc = ngx_http_process_request_header(r);
            if(rc != NGX_OK) {
                return ;
            }
            // 开始http请求的处理
            ngx_http_process_request(r);
            return ;
        }
    }
}

5. http请求的处理

在ngx_http_process_request中,将连接读写事件的回调处理均设置为ngx_http_request_handler方法,然后调用ngx_http_handler,而在ngx_http_handler中最终调用ngx_http_core_run_phases开始http的多阶段处理。

void ngx_http_process_request(ngx_http_request_t *r )
{
    ....
    c->read->handler = ngx_http_request_handler;
    c->write->handler = ngx_http_request_handler;
    c->read_event_handler = ngx_http_block_reading;
    ngx_http_handler(r);
    ngx_http_run_posted_requests(c);
}

void ngx_http_handler(ngx_http_request_t * r)
{
    ...
    // 开始http请求的多阶段处理
    r->write_event_handler = ngx_http_core_run_phases;
    ngx_http_core_run_phases(r);
}

6. 发送http请求响应

http请求响应回复一般会通过ngx_http_send_header发送http头部,通过ngx_http_output_filter发送http的包体。ngx_http_send_header和ngx_http_output_filter都是由一系列的filter模块组成,这些模块对响应数据进行加工处理,最终调用ngx_http_write_filter进行数据的发送。

ngx_int_t ngx_http_send_header(ngx_http_request_t *r)
{
    ....
    return ngx_http_top_header_filter(r);
}

ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
    ....
    rc = ngx_http_top_body_filter(r, in);
    ....
}

7. 结束http请求

一般来讲,结束http请求会调用ngx_http_finalize_request来完成。到这里,整个http的处理流程结束。

共有 人打赏支持
粉丝 64
博文 64
码字总数 75100
评论 (2)
摩云飞
改行专攻nginx了?
hncscwc

引用来自“摩云飞”的评论

改行专攻nginx了?
有个项目需要,就研究下
×
hncscwc
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: