ngx_http_init_headers_in_hash
1 定义ngx_http_init_headers_in_hash 函数 定义在 ./nginx-1.24.0/src/http/ngx_http.cstaticngx_int_tngx_http_init_headers_in_hash(ngx_conf_t*cf,ngx_http_core_main_conf_t*cmcf){ngx_array_theaders_in;ngx_hash_key_t*hk;ngx_hash_init_thash;ngx_http_header_t*header;if(ngx_array_init(headers_in,cf-temp_pool,32,sizeof(ngx_hash_key_t))!NGX_OK){returnNGX_ERROR;}for(headerngx_http_headers_in;header-name.len;header){hkngx_array_push(headers_in);if(hkNULL){returnNGX_ERROR;}hk-keyheader-name;hk-key_hashngx_hash_key_lc(header-name.data,header-name.len);hk-valueheader;}hash.hashcmcf-headers_in_hash;hash.keyngx_hash_key_lc;hash.max_size512;hash.bucket_sizengx_align(64,ngx_cacheline_size);hash.nameheaders_in_hash;hash.poolcf-pool;hash.temp_poolNULL;if(ngx_hash_init(hash,headers_in.elts,headers_in.nelts)!NGX_OK){returnNGX_ERROR;}returnNGX_OK;}ngx_http_init_headers_in_hash 函数的作用是 初始化一个哈希表headers_in_hash将预定义的 HTTP 请求头名称与其对应的处理结构进行映射 以便在请求处理时能够高效地根据头名称查找到相应的处理函数。2 详解1 函数签名staticngx_int_tngx_http_init_headers_in_hash(ngx_conf_t*cf,ngx_http_core_main_conf_t*cmcf)返回值 NGX_OK为 0表示函数执行成功哈希表初始化完成。 NGX_ERROR为 -1表示函数执行过程中发生错误参数 ngx_conf_t *cf 指向配置解析上下文 ngx_http_core_main_conf_t *cmcf 指向 ngx_http_core_main_conf_t 结构体的指针。 它是 HTTP 核心模块的主配置结构体。 用于存储 HTTP 核心模块的全局配置信息。 函数构建好的哈希表最终会存储在该结构体的 headers_in_hash 成员中2 逻辑流程1 局部变量 2 收集数据 2-1 初始化管理数据的数组 2-2 遍历收集数据填充到数组中管理 3 设置 hash 表配置参数 4 构建 hash 表 5 返回成功1 局部变量{ngx_array_theaders_in;ngx_hash_key_t*hk;ngx_hash_init_thash;ngx_http_header_t*header;2 收集数据2-1 初始化管理数据的数组if(ngx_array_init(headers_in,cf-temp_pool,32,sizeof(ngx_hash_key_t))!NGX_OK){returnNGX_ERROR;}为数组分配内存 headers_in 数组是一个临时动态数组 用于收集所有预定义 HTTP 请求头的哈希键信息包括头名称、预计算的哈希值以及对应的处理结构指针。 它作为中间容器在构建最终的 headers_in_hash 哈希表之前暂存这些数据 然后通过 ngx_hash_init 将这些键值对组织成高效的哈希表。 该数组使用临时内存池分配在配置解析完成后会被释放其生命周期仅存在于哈希表构建过程中。2-2 遍历收集数据填充到数组中管理for(headerngx_http_headers_in;header-name.len;header){hkngx_array_push(headers_in);if(hkNULL){returnNGX_ERROR;}hk-keyheader-name;hk-key_hashngx_hash_key_lc(header-name.data,header-name.len);hk-valueheader;}#1 遍历所有预定义的 HTTP 请求头结构 这些结构在 nginx 中静态定义包含头的名称和处理函数等信息。#2 在 headers_in 动态数组中扩展一个元素准备填充哈希键信息#3 记录该哈希键的键名用于后续哈希查找时的键值比较 ngx_hash_key_lc 的作用是先将字符串转换为小写不区分大小写然后计算哈希值 返回哈希值通常是 uint32_t 类型。 该哈希值被存储到 hk-key_hash 中。 将当前头结构指针 header 赋值给哈希键的 value 成员。 这样当通过哈希表查找到某个头时可以直接获得对应的 ngx_http_header_t 结构 其中包含了该头的处理函数指针和其他相关信息便于快速调用。3 设置 hash 表配置参数hash.hashcmcf-headers_in_hash;hash.keyngx_hash_key_lc;hash.max_size512;hash.bucket_sizengx_align(64,ngx_cacheline_size);hash.nameheaders_in_hash;hash.poolcf-pool;hash.temp_poolNULL;配置哈希表初始化参数。 它填充了 ngx_hash_init_t 结构体 告诉 Nginx 的哈希初始化函数 ngx_hash_init 如何创建哈希表、存到哪里、使用什么内存池以及性能参数是多少。ngx_hash_init_t 是 nginx 中用于 配置和初始化哈希表的参数结构体。 它集中定义了构建哈希表所需的各种属性 包括目标哈希表指针、哈希函数、桶数量限制、桶大小对齐、内存池等。 通过将该结构体传递给 ngx_hash_init() 函数 nginx 能够根据这些参数将一组键值对高效地组织成哈希表实现快速查找。 也就是说 ngx_hash_init_t 是一个记录配置参数的表格 它记录了构造哈希表所需要的配置参数#1 指定生成的哈希表结构体存放的地址。 #2 指定计算键的哈希值的函数 ngx_hash_key_lc 是一个将字符串转换为小写并计算哈希值的函数 #3 设定哈希表的最大桶bucket数量为 512。 哈希表内部由若干个桶组成每个桶是一个链表或数组用于存储冲突的元素。 max_size 限制了桶的上限确保哈希表不会占用过多内存。 预定义的请求头数量大约只有十几个512 是一个安全且性能良好的经验值 能够有效减少哈希冲突同时避免浪费内存。 #4 设置每个桶大小的“上限限制” 使用 ngx_align 宏将 64 按 ngx_cacheline_size通常为 64 字节对齐结果仍为 64。 意义决定了每个桶在内存中占用的空间大小上限。 对齐到 CPU 缓存行大小cache line可以避免伪共享false sharing提高 CPU 缓存利用效率。 这里选择 64 字节既保证了对齐也为桶内元素提供了足够的空间。 #5 指定哈希表名称 #6 指定分配哈希表内存所使用的内存池 即配置解析阶段的永久内存池 最终构建的哈希表需要一直存在 #7 指定初始化过程中使用的临时内存池 设为 NULL 表示不需要独立的临时池4 构建 hash 表if(ngx_hash_init(hash,headers_in.elts,headers_in.nelts)!NGX_OK){returnNGX_ERROR;}调用 ngx_hash_init这是 nginx 提供的哈希表初始化函数。 第一个参数 hash 指向之前填充好的 ngx_hash_init_t 结构体的指针。 该结构体包含了目标哈希表地址cmcf-headers_in_hash、 哈希函数ngx_hash_key_lc、桶大小、最大桶数、内存池等关键配置。 第二个参数 headers_in.elts 数组管理着需要组织为哈希表的数据 headers_in 数组的元素起始地址即 ngx_hash_key_t 类型键值对的数组首指针。 每个元素包含头名称key、预计算的哈希值key_hash和对应的头处理结构value。 第三个参数 headers_in.nelts headers_in 数组的元素个数即需要插入哈希表的键值对数量等于预定义 HTTP 请求头的个数。 函数功能 ngx_hash_init 根据 hash 中的参数将 headers_in 中的键值对组织成高效的哈希表 并存入 hash.hash 指向的地址即 cmcf-headers_in_hash。 它会处理哈希冲突、调整桶大小、分配内存等工作。 。 返回值 成功时返回 NGX_OK失败时返回 NGX_ERROR5 返回成功returnNGX_OK;}