10.2.2 管理server级别下的配置项

在解析main级别配置项时,如果发现了server{}配置项,就会回调ngx_http_core_server方法(该方法属于ngx_http_core_module模块),而在这个方法里则会开始解析srv级别的配置项,其流程如图10-2所示。

10.2.2 管理server级别下的配置项 - 图1

图 10-2 解析server{}块内配置项的流程

下面简要说明图10-2中的步骤:

1)在解析到server块时,首先会像解析http块一样,建立属于这个server块的ngx_http_conf_ctx_t结构体。在ngx_http_conf_ctx_t的3个成员中,main_conf将指向所属的http块下ngx_http_conf_ctx_t结构体的main_conf指针数组,而srv_conf和loc_conf都将重新分配指针数组,数组的大小为ngx_http_max_module,也就是所有HTTP模块的总数。

2)循环调用所有HTTP模块的create_srv_conf方法,将返回的结构体指针按照模块序号ctx_index保存到上述的srv_conf指针数组中。

3)循环调用所有HTTP模块的create_loc_conf方法,将返回的结构体指针按照模块序号ctx_index保存到上述的loc_conf指针数组中。

4)第1个HTTP模块就是ngx_http_core_module模块,它在create_srv_conf方法中将会生成非常关键的ngx_http_core_srv_conf_t配置结构体,这个结构体对应着当前正在解析的server块,这时,将ngx_http_core_srv_conf_t添加到全局的ngx_http_core_main_conf_t结构体的servers动态数组中,在图10-3中会看到这一点。

10.2.2 管理server级别下的配置项 - 图2

图 10-3 HTTP模块srv级别配置项结构体指针的内存示意图

5)解析当前server{}块内的所有配置项。

6)如果在server{}块内没有解析到listen配置项,则意味着当前的server虚拟主机并没有监听TCP端口,这不符合HTTP框架的设计原则。于是将开始监听默认端口80,实际上,如果当前进程没有权限监听1024以下的端口,则会改为监听8000端口。

由于http块只有1个,因此在10.2.1节中可以简单地给出main级别配置项的内存示意图。但http块内会包含任意个server块,对于每个server块都需要建立1个ngx_http_conf_ctx_t结构体,这些server块的ngx_http_conf_ctx_t结构体是通过ngx_array_t动态数组组织起来的,这其中的关系就比较复杂了,图10-3是它们简单的内存示意图。

图10-3是针对10.1节中的例子所画的示意图,在http块下有两个server块,分别表示虚拟主机名为A的配置块和虚拟主机名为B的配置块。解析每一个server块时都会创建一个新的ngx_http_conf_ctx_t结构体,其中的main_conf将指向http块下main_conf指针数组,而srv_conf和loc_conf数组则都会重新分配,它们的内容就是所有HTTP模块的create_srv_conf方法、create_loc_conf方法创建的结构体指针。

在10.2.1节中提到的main级别配置项中,ngx_http_core_module模块的ngx_http_core_main_conf_t结构体中有一个servers动态数组,如下所示。


typedef struct{

/存储指针的动态数组,每个指针指向ngx_http_core_srv_conf_t结构体的地址,也就是其成员类型为ngx_http_core_srv_conf_t**/

ngx_array_t servers;

……

}ngx_http_core_main_conf_t;


servers动态数组中的每一个元素都是一个指针,它指向用于表示server块的ngx_http_core_srv_conf_t结构体的地址(属于ngx_http_core_module模块)。ngx_http_core_srv_conf_t结构体中有1个ctx指针,它指向解析server块时新生成的ngx_http_conf_ctx_t结构体,具体如下所示。


typedef struct{

//指向当前server块所属的ngx_http_conf_ctx_t结构体

ngx_http_conf_ctx_t*ctx;

/当前server块的虚拟主机名,如果存在的话,则会与HTTP请求中的Host头部做匹配,匹配上后再由当前ngx_http_core_srv_conf_t处理请求/

ngx_str_t server_name;

……

}ngx_http_core_srv_conf_t;


这样,server块下以ngx_http_conf_ctx_t组织起来的所有配置项结构体,就会由servers动态数组关联起来。servers动态数组中的元素个数与http块下的server配置块个数是一致的。