zoukankan      html  css  js  c++  java
  • Nginx:处理HTTP请求

    参考资料<深入理解Nginx>(陶辉)

    处理HTTP请求

    接着上一次的内容,本次将说明HTTP框架是如何召集负责具体功能的各HTTP模块合作处理请求的。

    在http://www.cnblogs.com/runnyu/p/4918135.html的最后是通过ngx_http_process_request方法开始处理请求的,该方法流程如下图

    2.设置读、写事件的回调方法为ngx_http_request_handler方法,请求的后续处理都是通过ngx_http_request_handler方法进行的。

    6.设置ngx_http_request_t结构体的write_event_handler成员为ngx_http_core_run_phases方法。该方法可能会被多次调度来完成HTTP请求的处理。

    7.调用ngx_http_core_run_phases回调方法,该方法执行流程如下

    ngx_http_request_t结构体中的phase_handler成员(处理流程的核心)将决定执行到哪一阶段,关于该成员跟其相关的数据结构可以查看http://www.cnblogs.com/runnyu/p/4910952.html。

    该回调方法的源码如下

    void ngx_http_core_run_phases(ngx_http_request_t *r)
    {
        ngx_int_t rc;
        ngx_http_phase_handler_t *ph;
        
        cmcf=ngx_http_get_module_man_conf(r,ngx_http_core_module);
        ph=cmcf->phase_engine.handlers;
        
        while(ph[phase_handler].checker){
            rc=ph[r->phase_handler].checker(r,&ph[r->phase_hanlder]);
            if(rc==NGX_OK){
                return;
            }
        }
    }

    只有当相应的checker方法返回NGX_OK时才将控制权交还给Nginx的事件模块,否则将继续执行(checker方法中会修改phase_handler成员以向下执行)。

    当这个请求上对应的事件再次触发时,HTTP框架将回调ngx_http_request_handler方法开始处理请求(上面已经设置了该方法为其读、写事件的回调方法)。

    下图是ngx_http_request_handler方法的流程

    2.如果当前事件可写,将调用ngx_http_reqeust_t结构体中的write_event_handler方法。该方法在上面已经设置为ngx_http_core_run_phases,可见该方法会被多次调用。

    Checker方法

    checker方法是HTTP框架定义的,每一个HTTP处理阶段对应着相应着一个checker方法(有的阶段的checker方法一样),handler方法只有在checker方法中调用。

    checker方法的主要任务在于,根据phase_handler执行某个HTTP模块实现的回调方法,并根据方法的返回值决定:

    1.当前阶段是否已经结束

    2.下次要执行的回调方法是哪一个

    3.是立刻执行下一个回调方法还是先把控制权交还给epoll

    下面介绍HTTP框架中其中两个checker方法的介绍

    ngx_http_core_generic_phase

    在前面的http://www.cnblogs.com/runnyu/p/4910952.html下面有该方法的介绍,下面只给出该方法的流程图

    可见,checker方法主要是根据handler方法的返回值来改变phase_handler的值以用来控制handler方法的执行顺序的。

    ngx_http_core_content_phase

    ngx_http_core_content_phase是NGX_HTTP_CONTENT_PHASE阶段的checker方法。是我们开发HTTP模块时最常用的一个阶段。

    其余10个阶段中各HTTP模块的handler方法都是放在全局ngx_http_core_main_conf_t结构体中,而该阶段的handler方法则可以放在ngx_http_core_conf_t结构体中,这就是按需挂载的基础

    typedef struct ngx_http_core_loc_conf_s ngx_http_core_loc_conf_t
    struct
    ngx_http_core_loc_conf_s { ... ngx_http_handler_pt handler; ... }

    在我们最初的开发的HTTP模块中:http://www.cnblogs.com/runnyu/p/4871866.html

    当检测到mytest配置项后,调用ngx_http_mytest方法将上面ngx_http_core_loc_conf_t的handler成员设置为自己的handler函数,实现了按需挂载。

    事实上,在NGX_HTTP_FIND_CONFIG_PHASE阶段就会把ngx_http_request_t结构体的content_handler成员设置为匹配请求URI的location下的ngx_http_core_loc_conf_t结构体的handler成员。

    下面是该checker方法的流程图,可以看出是如何实现按需挂载的

    处理HTTP包体

    在接收完HTTP头部后,就开始调用各HTTP模块处理请求了,然后由HTTP模块决定如何处理包体(handler函数)。

    1.接收包体

    ngx_int_t ngx_http_read_client_request_body(ngx_http_request *r,ngx_http_client_body_handler_pt post_handler);
    typedef void (*ngx_http_client_body_handler_pt) (ngx_http_request_t *r);

    接收到的包体保存在ngx_http_reqeust_body_t中,一般调用该函数的handler函数会接着返回NGX_DONE。

    在完成接收动作之后,会调用post_handler函数继续处理请求。

    2.放弃接收包体(Nginx必须接收包体,但不做处理)

    ngx_int ngx_http_discard_reqeust_body(ngx_http_request_t *r);

    调用该函数的handler函数继续处理请求,Nginx会异步地接收跟丢弃包体。

    发送HTTP响应

    显然,发送HTTP响应也是在handler函数中调用的。

    1.发送响应头

    ngx_int_t ngx_http_send_header(ngx_http_request_t *r);

    该方法会异步地根据ngx_http_reqeust_t中的header_out成员将HTTP头部发送给客户端(经过各个过滤模块)。

    2.发送响应体

    ngx_int_t ngx_http_output_filter(ngx_http_request_t *r,ngx_chain_t *in);

    该方法会异步地根据参数in将HTTP响应体发送给客户端(经过各个过滤模块)。

  • 相关阅读:
    C#中的Excel操作【1】——设置Excel单元格的内容,打开Excel文件的一种方式
    Java 在指定目录建立指定文件名的文件 并输入内容
    JSP基础——属性保存范围和request对象
    JSP基础总结(运行机制、脚本元素、指令元素、动作元素)
    weblogic 清除缓存
    oracle 分区表详解
    ORA-00257: archiver error的解决方法
    oracle中job定时器任务
    timestamp类型在jsp页面输出格式化方法
    cmd中测试常用到的命令汇总
  • 原文地址:https://www.cnblogs.com/runnyu/p/4922558.html
Copyright © 2011-2022 走看看