ngx_http_optimize_servers
1 定义ngx_http_optimize_servers 函数 定义在 ./nginx-1.24.0/src/http/ngx_http.cstaticngx_int_tngx_http_optimize_servers(ngx_conf_t*cf,ngx_http_core_main_conf_t*cmcf,ngx_array_t*ports){ngx_uint_tp,a;ngx_http_conf_port_t*port;ngx_http_conf_addr_t*addr;if(portsNULL){returnNGX_OK;}portports-elts;for(p0;pports-nelts;p){ngx_sort(port[p].addrs.elts,(size_t)port[p].addrs.nelts,sizeof(ngx_http_conf_addr_t),ngx_http_cmp_conf_addrs);/* * check whether all name-based servers have the same * configuration as a default server for given address:port */addrport[p].addrs.elts;for(a0;aport[p].addrs.nelts;a){if(addr[a].servers.nelts1#if(NGX_PCRE)||addr[a].default_server-captures#endif){if(ngx_http_server_names(cf,cmcf,addr[a])!NGX_OK){returnNGX_ERROR;}}}if(ngx_http_init_listening(cf,port[p])!NGX_OK){returnNGX_ERROR;}}returnNGX_OK;}ngx_http_optimize_servers 函数的作用是 对 Nginx HTTP 模块中所有监听端口上的地址配置进行排序和优化 检查基于名称的虚拟主机配置的一致性并最终初始化实际监听套接字将配置转换为运行时可用的监听结构。 简单说它将解析后的服务器配置转化为高效的运行时数据结构并准备监听端口。2 详解1 函数签名staticngx_int_tngx_http_optimize_servers(ngx_conf_t*cf,ngx_http_core_main_conf_t*cmcf,ngx_array_t*ports)返回值 NGX_OK0成功 NGX_ERROR-1失败参数 ngx_conf_t *cf 指向配置解析上下文 ngx_http_core_main_conf_t *cmcf HTTP 核心模块的主配置结构体 存储全局 HTTP 配置 ngx_array_t *ports 监听端口配置数组 三个参数分别代表 解析环境cf管资源、 全局配置cmcf管输出 和 待处理数据ports管输入 职责清晰。2 逻辑流程1 局部变量 2 输入检查 3 遍历 优化 4 返回成功1 局部变量{ngx_uint_tp,a;ngx_http_conf_port_t*port;ngx_http_conf_addr_t*addr;2 输入检查if(portsNULL){returnNGX_OK;}判断传入的 ports 指针是否为 NULL 若 ports NULL 就无事可做 直接返回 成功3 遍历 优化portports-elts;for(p0;pports-nelts;p){ngx_sort(port[p].addrs.elts,(size_t)port[p].addrs.nelts,sizeof(ngx_http_conf_addr_t),ngx_http_cmp_conf_addrs);/* * check whether all name-based servers have the same * configuration as a default server for given address:port */addrport[p].addrs.elts;for(a0;aport[p].addrs.nelts;a){if(addr[a].servers.nelts1#if(NGX_PCRE)||addr[a].default_server-captures#endif){if(ngx_http_server_names(cf,cmcf,addr[a])!NGX_OK){returnNGX_ERROR;}}}if(ngx_http_init_listening(cf,port[p])!NGX_OK){returnNGX_ERROR;}}#1 获取 ports 动态数组的起始地址#2 遍历 ports 数组中的每一个端口配置#3 作用对当前端口下的所有地址配置进行排序。 参数详解 port[p].addrs.elts当前端口下地址数组的首元素指针。 (size_t) port[p].addrs.nelts地址数量要排序的元素个数。 sizeof(ngx_http_conf_addr_t)每个地址结构的大小。 ngx_http_cmp_conf_addrs比较函数用于确定地址的先后顺序。 排序规则 比较函数按照地址的具体程度排序 通常将最具体的 IP 地址如 192.168.1.1排在前 通配地址如 0.0.0.0 或 ::排在后。 这保证了后续处理中默认服务器选择的确定性 以及 server_name 匹配时的优先级正确性。 意义 排序是“优化”的第一步 使得后续的哈希表构建和监听初始化具有一致且可预测的顺序。#4 获取当前端口下地址数组的首地址赋值给局部变量 addr#5 遍历当前端口下的每一个地址#6 判断当前地址上配置的虚拟服务器数量是否大于 1。 如果数量 1 说明存在多个基于名称的虚拟主机共享同一个 IP:Port 需要为这些 server_name 建立高效的匹配数据结构如哈希表 否则可以直接使用唯一服务器#7 条件编译当 Nginx 编译时启用了 PCREPerl Compatible Regular Expressions库时 额外判断默认服务器是否使用了正则表达式捕获。 addr[a].default_server 指向该地址的默认服务器 即当没有匹配的 server_name 时回落的服务器。 captures 是 ngx_http_core_srv_conf_t 中的一个标志位 表示该服务器的 server_name 指令中是否包含正则表达式如 server_name ~^www\.example\.com$。 正则表达式可能包含捕获分组需要特殊处理。 逻辑 如果编译支持正则且默认服务器使用了正则匹配 也需要调用 ngx_http_server_names 来构建正则表达式相关结构。#8 调用 ngx_http_server_names 函数对当前地址进行虚拟主机名称的优化。 参数 cf配置上下文用于内存分配和日志。 cmcfHTTP 核心主配置 addr[a]当前地址的配置结构体指针。 功能该函数会 将配置文件中解析出的 server_name 指令编译为高效的运行时匹配结构 实现基于域名的虚拟主机Name-based Virtual Hosting快速路由。#9 调用 ngx_http_init_listening 函数 该函数会 遍历 port[p] 下的所有地址为每个地址创建一个监听对象ngx_listening_t。 设置套接字选项如 SO_REUSEADDR、非阻塞等。 将监听对象加入全局 cf-cycle-listening 数组。4 返回成功returnNGX_OK;}