zoukankan      html  css  js  c++  java
  • 处理request信息的ngx_http_process_request

       在处理完http的头部信息后  然后在 处理request-body信息ngx_http_process_request--------

    -----------ngx_http_process_request_headers(ngx_http_process_request_header)头部行解析完毕后调用函数ngx_http_process_request_header

    ngx_http_process_request:设置read和write的回调函数ngx_http_request_handler,ngx_http_request_handler通过状态机来判断是读事件还是写事件。

    void
    ngx_http_process_request(ngx_http_request_t *r) 
    {
        ngx_connection_t  *c;
    
        c = r->connection;
    
    #if (NGX_HTTP_SSL)
    
    -----------------------
    #endif
        /*
        由于现在已经开始准备调用各HTTP模块处理请求了,因此不再存在接收HTTP请求超时的问题????,那就需要从定时器中把当前连接的读事件移除了。
        检查读事件对应的timer_set标志位,力1时表示读事件已经添加到定时器中了,这时需要调用ngx_del_timer从定时器中移除读事件;
         */
        if (c->read->timer_set) {//ngx_http_read_request_header中读取不到数据的时候返回NGX_AGIN,会添加定时器和读事件表示继续等待客户端数据到来
            ngx_del_timer(c->read, NGX_FUNC_LINE);
        }
    
    #if (NGX_STAT_STUB)
        (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
        r->stat_reading = 0;
        (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
        r->stat_writing = 1;
    #endif
    
    /*
    从现在开始不会再需要接收HTTP请求行或者头部,所以需要重新设置当前连接读/写事件的回调方法。在这一步骤中,将同时把读事件、写事件的回调
    方法都设置为ngx_http_request_handler方法,请求的后续处理都是通过ngx_http_request_handler方法进行的。
     */
        c->read->handler = ngx_http_request_handler; //由读写事件触发ngx_http_request_handler  //由epoll读事件在ngx_epoll_process_events触发
        c->write->handler = ngx_http_request_handler;   //由epoll写事件在ngx_epoll_process_events触发
    
    /*
    设置ngx_http_request_t结构体的read_event_handler方法gx_http_block_reading。当再次有读事件到来时,将会调用ngx_http_block_reading方法
    处理请求。而这里将它设置为ngx_http_block_reading方法,这个方法可认为不做任何事,它的意义在于,目前已经开始处理HTTP请求,除非某个HTTP模块重新
    设置了read_event_handler方法,否则任何读事件都将得不到处理,也可似认为读事件被阻 塞了。
    */
        r->read_event_handler = ngx_http_block_reading; //表示暂时不要读取客户端请求    
    
        /* ngx_http_process_request和ngx_http_request_handler这两个方法的共通之处在于,它们都会先按阶段调用各个HTTP模块处理请求,再处理post请求 */
        ngx_http_handler(r); //这里面会执行ngx_http_core_run_phases,执行11个阶段
    
    /*
    HTTP框架无论是调用ngx_http_process_request方法(首次从业务上处理请求)还是ngx_http_request_handler方法(TCP连接上后续的事件触发时)处理
    请求,最后都有一个步骤,就是调用ngx_http_run_posted_requests方法处理post请求
    
    11个阶段执行完毕后,调用ngx_http_run_posted_requests方法执行post请求,这里一般都是对subrequest进行处理
    */
        ngx_http_run_posted_requests(c); /*  */
    }

    ngx_http_block_reading:del event at epoll

    /*
    把读事件从epoll中移除。只对epoll lt模式其作用它的意义在于,目前已经开始处理HTTP请求,除非某个HTTP模块重新设置了read_event_handler方法,
    否则任何读事件都将得不到处理,也可似认为读事件被阻 塞了。
    
    注意这里面会调用ngx_del_event,因此如果需要继续读取客户端请求内容,需要加上ngx_add_event,例如可以参考下ngx_http_discard_request_body
    */
    void
    ngx_http_block_reading(ngx_http_request_t *r)
    {
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "http reading blocked");
    
        /* aio does not call this handler */
    
        if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
            && r->connection->read->active)
        {
            if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
                ngx_http_close_request(r, 0);
            }
        }
    }
    • ngx_http_request_handler

    HTTP框架无论是调用ngx_http_process_request方法(首次从业务上处理请求)还是ngx_http_request_handler方法(TCP连接上后续的事件触发时)处理
    请求,最后都有一个步骤,就是调用ngx_http_run_posted_requests方法处理post请求
    *客户端事件处理handler一般(write(read)->handler)一般为ngx_http_request_handler, 和后端的to server handler一般(write(read)->handler)一般为ngx_http_upstream_handler
    */
    static void
    ngx_http_request_handler(ngx_event_t *ev)
    {
        ngx_connection_t    *c;
        ngx_http_request_t  *r;
    
    /*
    ngx_http_request_handler是HTTP请求上读/写事件的回调方法。在ngx_event_t结构体表示的事件中,data成员指向了这个事件对应的ngx_connection_t连接,
    在HTTP框架的ngx_connection_t结构体中的data成员则指向了ngx_http_request_t结构体
    */
        c = ev->data;
        r = c->data;
    
        ngx_http_set_log_request(c->log, r);
    
        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
                       "http run request(ev->write:%d): "%V?%V"", ev->write, &r->uri, &r->args);
    
    /*
     检查这个事件的write可写标志,如果write标志为l,则调用ngx_http_request_t结构体中的write event- handler方法。注意,我们在ngx_http_handler
     方法中已经将write_event_handler设置为ngx_http_core_run_phases方法,而一般我们开发的不太复杂的HTTP模块是不会重新设置write_event_handler方
     法的,因此,一旦有可写事件时,就会继续按照流程执行ngx_http_core_run_phases方法,并继续按阶段调用各个HTTP模块实现的方法处理请求。
    
    如果一个事件的读写标志同时为1时,仅write_event_handler方法会被调用,即可写事件的处理优先于可读事件(这正是Nginx高性能设计的体现,
    优先处理可写事件可以尽快释放内存,尽量保持各HTTP模块少使用内存以提高并发能力)。因为服务器发送给客户端的报文长度一般比请求报文大很多
     */
       //当ev为ngx_connection_t->write 默认write为1;当ev为ngx_connection_t->read 默认write为0
        if (ev->write) { //说明ev是ngx_connection_t->write
            r->write_event_handler(r); //ngx_http_core_run_phases
    
        } else {//说明ev是ngx_connection_t->read事件 
            r->read_event_handler(r);
        }
    
    /*
    HTTP框架无论是调用ngx_http_process_request方法(首次从业务上处理请求)还是ngx_http_request_handler方法(TCP连接上后续的事件触发时)处理
    请求,最后都有一个步骤,就是调用ngx_http_run_posted_requests方法处理post请求
    */
    /* ngx_http_process_request和ngx_http_request_handler这两个方法的共通之处在于,它们都会先按阶段调用各个HTTP模块处理请求,再处理post请求 ---
    ------主要用于处理subrequest 子请求
    */ ngx_http_run_posted_requests(c); }
  • 相关阅读:
    Python之操作MySQL数据库
    Python之进程与线程
    Python之socket网络编程
    网络基础之网络协议
    Python之log的处理方式
    11 python 操作mysql数据库
    10 线程 协程 socketserver 基于udp的socketserver
    9 异常处理 操作系统 进程线程 队列+生产消费者模型 进程同步 回调函数
    6 常用模块 (time,random,os,sys,shutil, json&pickle, shelve,xml,configparser,hashlib,suprocess,logging)
    ubuntu16上安装安装Docker图形化管理界面-Shipyard中文版
  • 原文地址:https://www.cnblogs.com/codestack/p/13487857.html
Copyright © 2011-2022 走看看