社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  NGINX

nginx的11个处理阶段概述

郑尔多斯 • 6 年前 • 589 次点击  
阅读 11

nginx的11个处理阶段概述

微信公众号:郑尔多斯
关注可了解更多的Nginx知识。任何问题或建议,请公众号留言;
关注公众号,有趣有内涵的文章第一时间送达!
请关注个人博客, 戳这里

解析完请求头部之后调用ngx_http_process_request()函数

// 进入http的11个阶段处理
static void ngx_http_process_request(ngx_http_request_t *r)
{
    ngx_connection_t  *c;

    c = r->connection;

    if (r->plain_http) {
        ngx_log_error(NGX_LOG_INFO, c->log0,
                      "client sent plain HTTP request to HTTPS port");
        ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
        return;
    }


    if (c->read->timer_set) {
        ngx_del_timer(c->read);
    }

    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(r);

    ngx_http_run_posted_requests(c);
}
复制代码

这个函数是在解析完http请求头之后调用的,我们分析一下他的功能:
1、删除定时器,因为http的头部已经解析完了,要进入http处理阶段了,所以可以删除原先的定时器了。
2、将connection的读写事件回调函数都设置为ngx_http_request_handler。代码如下:
epoll_wait()监控到当前connection上发生了读写事件,就会调用ngx_http_request_handler函数,而这个函数根据读写事件的类型分别调用http 连接的read_event_handlerwrite_event_handler()函数,其实不明白这里为什么要这么做。 然后调用ngx_http_run_posted_requests()函数处理子请求。也就是说,每当连接上面有读写事件发生的时候都会调用ngx_http_run_posted_requests来处理子请求。

static void ngx_http_request_handler(ngx_event_t *ev)
{
    ngx_connection_t    *c;
    ngx_http_request_t  *r;
    ngx_http_log_ctx_t  *ctx;

    c = ev->data;
    r = c->data;

    ctx = c->log->data;
    ctx->current_request = r;

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log0,
                   "http run request: \"%V?%V\"", &r->uri, &r->args);

    if (ev->write) {
        r->write_event_handler(r);

    } else {
        r->read_event_handler(r);
    }

    ngx_http_run_posted_requests(c);
}

  3、调用ngx_http_handler()函数
void
ngx_http_handler(ngx_http_request_t *r)
{
    ngx_http_core_main_conf_t  *cmcf;

    r->connection->log->action = NULL;

    r->connection->unexpected_eof = 0;

    if (!r->internal) {
        switch (r->headers_in.connection_type) {
        case 0:
            r->keepalive = (r->http_version > NGX_HTTP_VERSION_10);
            break;

        case NGX_HTTP_CONNECTION_CLOSE:
            r->keepalive = 0;
            break;

        case NGX_HTTP_CONNECTION_KEEP_ALIVE:
            r->keepalive = 1;
            break;
        }

        r->lingering_close = (r->headers_in.content_length_n > 0);
        r->phase_handler = 0;

    } else {
        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
        r->phase_handler = cmcf->phase_engine.server_rewrite_index;
    }

    r->valid_location = 1;
    r->write_event_handler = ngx_http_core_run_phases;
    ngx_http_core_run_phases(r);
}
复制代码

这个函数的主要作用就是将http连接的write_event_handler设置为ngx_http_core_run_phases函数,然后调用ngx_http_core_run_phases函数,这个函数就是进入nginx的11个处理阶段。

4、调用ngx_http_run_posted_requests函数处理子请求。



综上所述,当epoll_wait()监控到connection上面有读写事件的时候会调用ngx_http_core_run_phase()函数进行11个阶段的处理。
在调用ngx_http_core_run_phases()的过程中,如果某一个处理阶段的checker函数返回了NGX_OK,那么从代码中可以看到,就会推出 ngx_http_core_run_phases()函数,这个时候nginx的控制权就返回给了epoll模块,只能等待发生下一个事件的时候继续调用ngx_http_core_run_phase()进行处理。

// nginx的核心处理函数
void ngx_http_core_run_phases(ngx_http_request_t *r)
{
    ngx_int_t                   rc;
    ngx_http_phase_handler_t   *ph;
    ngx_http_core_main_conf_t  *cmcf;

    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

    ph = cmcf->phase_engine.handlers;

    while (ph[r->phase_handler].checker) {

        rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);

        if (rc == NGX_OK) {
            return;
        }
    }
}
复制代码



总结一下这个流程:
处理流程
处理流程

喜欢本文的朋友们,欢迎长按下图关注订阅号郑尔多斯,更多精彩内容第一时间送达

郑尔多斯
郑尔多斯
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/34756
 
589 次点击