Nginx系列(十四):支持通配符的散列表

本文深入解析了Nginx中ngx_hash_keys_arrays_t结构体的用途,以及如何使用ngx_hash_keys_array_init等函数构建无通配符与含通配符的Hash表。通过实例演示了通配符key的处理过程,以及如何避免key冲突。

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

大家看到在构建一个ngx_hash_wildcard_t的时候,需要对通配符的哪些key进行预处理。这个处理起来比较麻烦。而当有一组key,这些里面既有无通配符的key,也有包含通配符的key的时候。我们就需要构建三个hash表,一个包含普通的key的hash表,一个包含前向通配符的hash表,一个包含后向通配符的hash表(或者也可以把这三个hash表组合成一个ngx_hash_combined_t)。在这种情况下,为了让大家方便的构造这些hash表,nginx提供给了此辅助类型。

1. ngx_hash_keys_arrays_t

在这里插入图片描述
以无通配符为例,该结构体用于散列表形成前的初始化。其中,keys_hash是一个分离链接法解决碰撞的散列表,每个str用来保存key,该散列表的作用是在将节点加入keys前,先检查keys_hash,避免keys中节点出现key冲突情况。
对于前向通配符情况,例如::“*.abc.com”,保存在keys->key中的字符串是“com.abc.”;“.abc.com”,保存在keys->key中的字符串是“com.abc”,两者差异是“.abc.com”既可以匹配www.abc.com,又可以匹配abc.com。

typedef struct {
ngx_uint_t        hsize;
ngx_pool_t       *pool;
ngx_pool_t       *temp_pool;
ngx_array_t       keys;
ngx_array_t      *keys_hash;
ngx_array_t       dns_wc_head;
ngx_array_t      *dns_wc_head_hash;
ngx_array_t       dns_wc_tail;
ngx_array_t      *dns_wc_tail_hash;
} ngx_hash_keys_arrays_t;
hsize将要构建的hash表的桶的个数。对于使用这个结构中包含的信息构建的三种类型的hash表都会使用此参数。
pool构建这些hash表使用的pool。
temp_pool在构建这个类型以及最终的三个hash表过程中可能用到临时pool。该temp_pool可以在构建完成以后,被销毁掉。这里只是存放临时的一些内存消耗。
keys这是个二维数组,第一个维度代表的是bucket的编号,那么keys_hash[i]中存放的是所有的key算出来的hash值对hsize取模以后的值为i的key。假设有3个key,分别是key1,key2和key3假设hash值算出来以后对hsize取模的值都是i,那么这三个key的值就顺序存放在keys_hash[i][0],keys_hash[i][1], keys_hash[i][2]。该值在调用的过程中用来保存和检测是否有冲突的key值,也就是是否有重复。
dns_wc_head放前向通配符key被处理完成以后的值。比如:“*.abc.com” 被处理完成以后,变成 “com.abc.” 被存放在此数组中。
dns_wc_tail存放后向通配符key被处理完成以后的值。比如:“mail.xxx.*” 被处理完成以后,变成 “mail.xxx.” 被存放在此数组中。
dns_wc_head_hash该值在调用的过程中用来保存和检测是否有冲突的前向通配符的key值,也就是是否有重复。
dns_wc_tail_hash该值在调用的过程中用来保存和检测是否有冲突的前向通配符的key值,也就是是否有重复。
2. ngx_hash_keys_array_init

对ngx_hash_keys_arrays_t进行初始化。

3. ngx_hash_add_key

将(key, value)对加入ngx_hash_keys_arrays_t初始化结构体,即填充该结构体的keys数组。

4. ngx_hash_init

形成无通配符的散列表。

5. ngx_hash_wildcard_init(形成含有通配符的散列表)

这里的传入参数names数组是经过处理后的字符串数组。对于字符串数组“.test.yexin.com”、“.yexin.com”、“.example.com”、“*.example.org”、“.yexin.org”处理完成之后就变成了“com.yexin.test.”、“com.yexin”、“com.example.”、“org.example.”、“org.yexin”。

1)把所有字符串"com.yexin.test."、“com.yexin”、“com.example.”、“org.example.”、“org.yexin"的第一个key字段提取出来,那么只有两个不相同的字段“com”、“org”。将这两个字段放入curr_names数组。
2)第一个key字段为"com"的字符串有"com.yexin”、“com.yexin.test.”、“com.example.”,那么剩余部分字符串即为"yexin"、“yexin.test”、“example”,存储next_names数组。
转图
3)对next_names数组进行ngx_hash_wildcard_init递归调用。
4)将curr_names数组进行ngx_hash_init调用形成散列表。
转图

00 - value 是 “example.com” 和 “.example.com"的数据指针
01 - value 仅仅是"
.example.com"的数据指针
10 - value 是 支持通配符哈希表是 “example.com” 和”.example.com" 指针
11 - value 仅仅是支持通配符哈希表是 "
.example.com"的指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值