按 IP 最长前缀选择配置值
nginx geo 的 CIDR 模式使用二进制 radix tree,为请求地址查找最具体的网络前缀配置。
相关概念
工程问题#
配置可能同时包含默认值、大网段与更具体的子网;查找需要让最长匹配前缀覆盖较宽泛的规则。
实际实现#
IPv4 和 IPv6 分别调用 32 位与 128 位 radix 查找。节点沿地址位分叉,查找途中保留已命中的配置值。
处理流程#
- 加载 CIDR 前缀及其值
- 将请求来源解析为 IP 地址
- 按地址位沿树向下查找
- 返回最具体的已匹配值
源码片段#
固定版本 · 原文摘录src/core/ngx_radix_tree.crelease-1.26.3 · L243–L263
243 bit = 0x80000000;244 value = NGX_RADIX_NO_VALUE;245 node = tree->root;246247 while (node) {248 if (node->value != NGX_RADIX_NO_VALUE) {249 value = node->value;250 }251252 if (key & bit) {253 node = node->right;254255 } else {256 node = node->left;257 }258259 bit >>= 1;260 }261262 return value;263}ngx_radix32tree_find
从最高位起逐位选择左右子树;每遇到带值节点便覆盖 value,最终返回最深的已匹配前缀值。geo 的 CIDR 模式调用此 IPv4 实现,IPv6 对应另一个 128 位函数。
变量声明在片段上方;这是逐位二叉 radix 查找,不应标为路径压缩 Patricia trie,geo ranges 模式也不使用此流程。
收益与取舍#
工程分析带来的收益
- 查询长度受地址位数约束
- 共享网络前缀可复用路径
付出的代价
- 工程分析:逐位节点增加指针和分支开销
- 源地址可信性仍需正确配置代理链
可比较的选择
范围数组适合预处理后的地址区间;重叠前缀语义需转换为不重叠范围。
版本与适用范围#
对应 geo 的 CIDR 模式;ranges 模式采用不同表示。geo 只是映射规则,不自带地理位置数据库。
参考来源#
源码、官方文档与原始论文01
nginx · ngx_http_geo_cidr_variable
源码release-1.26.3src/http/modules/ngx_http_geo_module.c · ngx_http_geo_cidr_variable
相关实现与比较#
1 个相关案例用压缩前缀树组织 token 序列,让多轮对话和分支生成共享已有 KV。
附源码片段 · 缓存与复用