10.2.2 管理server级别下的配置项
在解析main级别配置项时,如果发现了server{}配置项,就会回调ngx_http_core_server方法(该方法属于ngx_http_core_module模块),而在这个方法里则会开始解析srv级别的配置项,其流程如图10-2所示。
图 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-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配置块个数是一致的。