Nginx-HTTP框架的初始化

本文详细介绍了Nginx的HTTP框架结构,包括解析http{}、server块和location配置,以及HTTP请求的11个处理阶段。讲解了如何向特定阶段添加处理器,并强调content阶段的处理方法。还提到了监听端口管理和配置结构体的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原创:https://blog.youkuaiyun.com/ndzjx/article/details/89222809

 

HTTP框架大致由1个核心模块(ngx_http_module)、两个HTTP模块(ngx_http_core_module、ngx_http_upstream_module)组成,它将负责调度其他HTTP模块来一起处理用户请求。首要任务是通过ngx_http_module_t接口中的方法来管理所有HTTP模块的配置项。

Server虚拟主机会以散列表的数据结构组织起来,高效查询。

Location表达式会以一个静态的二叉查找树组织起来。不使用红黑树,是因为location是从nginx.conf中读取到的,是静态不变的,不存在运行过程中添加删除的场景,而且红黑树的查询效率也没有重新构造的静态的完全平衡二叉树高。(ngx_http_init_locations/nginx_http_init_static_location_trees)

typedef struct {
    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);
    ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);

    void       *(*create_main_conf)(ngx_conf_t *cf);
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);

    void       *(*create_srv_conf)(ngx_conf_t *cf);
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);

    void       *(*create_loc_conf)(ngx_conf_t *cf);
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;

1:处理http{}块内的main级别配置项时,对每个HTTP模块,都会调用create_main_conf、create_srv_conf、create_loc_conf建立3个结构体,这是为了把同时出现在http{},server{},location{}内的相同配置项进行合并而做的准备。

2:处理server{}内的srv级别配置项时,需要调用每个HTTP模块的create_srv_conf、create_loc_conf

3:处理location{}内的loc级别配置项时,调用HTTP每个模块的create_loc_conf方法建立结构体

 

解析http{}

ngx_http_core_module模块完成了HTTP框架的大部分功能,而它又是一个HTTP模块,使用到了比较关心的3个结构体(ngx_http_core_main_conf_t、ngx_http_core_srv_conf_t、ngx_http_core_loc_conf_t)

typedef struct {
    void        **main_conf;
    void        **srv_conf;
    void        **loc_conf;
} ngx_http_conf_ctx_t;

通过ngx_cycle_t找到main级别的配置结构体:

#define ngx_http_cycle_get_module_main_conf(cycle, module)                    \
    (cycle->conf_ctx[ngx_http_module.index] ?                                 \
        ((ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index])      \
            ->main_conf[module.ctx_index]:                                    \
        NULL)

 

 

解析server块

首先会像解析http块一样,建立属于这个server块的ngx_http_conf_ctx_t结构体。

如果server{}内没有解析到listen配置项,默认监听端口80,当进程没有权限监听1024以下的端口时,则会监听8000端口。

ngx_http_core_module模块的ngx_http_core_main_conf_t结构中有一个servers动态数组。

 

 

 

解析location配置块

仍然会像解析http块一样,先建立ngx_http_conf_ctx_t结构体。

 

同一个server下的location, ngx_http_core_loc_conf_t结构体构成一个双向链表。(非侵入式链表)

 

location下还可以嵌套location,同样,会生成链表。

 

 

 

监听端口的管理:

监听端口属于server虚拟主机,由listen配置项决定,与server{}块对应的ngx_http_core_srv_conf_t结构体密切相关。每一个TCP端口,都将使用一个独立的ngx_http_conf_port_t结构体表示。

ngx_http_conf_port_t的addrs动态数组可能不太容易理解。如:对同一个端口8000,我们可以同时监听127.0.0.1:8000、173.39.160.51:8000这两个地址,当一台物理机器具备多个IP地址时这是很有用的

监听端口与server虚拟主机的关系:

 

 

 

HTTP请求的11个阶段:

    1)post_read : 接受到完整的http头部后处理的阶段

    2)server_rewrite:URI与location匹配前,可以修改URI(重定向)

    3)find_config:根据URI寻找匹配的location表达式

    4)rewrite:location匹配后可以再修改URI

    5)post_rewrite:rewrite修改URI后,防止错误的nginx.conf配置导致死循环,如果一个请求超过10次重定向,就认为i进入了rewrite死循环。

    6)pre_access:处理访问权限前,可以介入的阶段

    7)access:是否允许请求访问Nginx服务器

    8)post_access:如果不允许访问,向用户发送拒绝服务的错误响应。

    9)pre_content:包含try_files指令,访问静态文件资源

    10)content:处理HTTP请求内容的阶段

    11)log:处理完请求后记录日志的阶段

其中:find_config、post_rewrite、post_access、pre_content 4个阶段不允许HTTP模块加入自己的ngx_http_handler_pt方法处理用户请求,它们仅由HTTP框架实现。

struct ngx_http_phase_handler_s {
    ngx_http_phase_handler_pt  checker; // 由ngx_http_core_module实现
    ngx_http_handler_pt        handler; 
    ngx_uint_t                 next; // 使得处理阶段不必按顺序依次执行
};

ngx_http_phase_engine_t结构体就是所有ngx_http_phase_handler_t组成的数组。此结构体在全局的ngx_http_core_main_conf_t结构体中。ngx_http_core_main_conf_t中还有一个phases数组,保存11个阶段每个阶段要执行的handlers

typedef struct {
    ngx_http_phase_handler_t  *handlers;
    ngx_uint_t                 server_rewrite_index; // 跳转到server_rewrite阶段处理
    ngx_uint_t                 location_rewrite_index;  // 跳转的rewrite
} ngx_http_phase_engine_t;

 

向指定阶段添加handler的方法大致如下:

在ngx_http_module_t接口的postconfiguration方法中将自定义的方法添加到handler动态数组中。

h = ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers);

if (h == NULL) {

return NGX_ERROR;

}

*h = ngx_http_realip_handler;

 

其中,content阶段还有一个独有的方法可以添加handler:

把希望处理请求的ngx_http_handler_pt方法设置到location相关的ngx_http_core_loc_conf_t结构体的handler指针中。

好处是:

处理方法不再应用于所有HTTP请求,仅URI匹配时才会被调用。

注意:

这种情况下,每个content阶段只能有一个ngx_http_handler_pt处理方法。这种方式优先于使用postconfiguration设置的方法,postconfiguration设置的方法会失效。

 

 

ngx_http_block方法,包括了HTTP框架的完整初始化流程:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值