《深入剖析ngx》——变量机制

1. ngx对变量性质的定义

用户可以在配置文件中使用变量,如

http_user_agent 就是变量,如上会根据 若使用IE访问 重写url。
ngx变量只有字符串类型,可以有用户定义的配置赋值,也可以由 ngx 自动赋值(如上,每次收到请求 自动对 http_user_agent 赋值)。
变量在配置文件的标志是 使用 $。
ngx使用惰性求值 赋值变量,即 当使用变量时,才 求值。这样的好处是 ngx可能定义了上百个变量,但是配置文件中只使用了几个,所以只需要求那几个变量。

2. 变量实现


ngx定义了 变量类型 ngx_http_variable_value_t , 变量值类型 ngx_variable_value_t

在解析配置前,ngx会统计所有支持的变量。
在每个 模块的 moulde->preconfiguration 回调函数,将自己支持的变量 加入 http核心配置 ngx_http_core_main_conf_t 的 variables_keys字段

如 ngx_http_core_module 在 preconfiguration 回调函数 统计自己的变量

ngx_hash_add_key() 实际上 是 往变量 cmcf->variables_keys 新增元素。
其他模块也是向 cmcf->variables_keys 添加变量

总之,当ngx配置解析完成,cmcf->variables_keys 记录了所有支持的变量。

解析配置文件时,将被使用的变量添加到 cmcf->variables
若配置文件出现 set $file aa; 则先定义变量,再对其赋值。
有些变量在ngx内部被使用,也会添加到 cmcf->variables

最后,cmcf->variables 记录了可能被使用的变量,所以需要对其合法性进行验证。在 ngx_http_variable_init_var() 实现,
遍历所有 cmcf->variables 变量,是否在 cmcf->variables_keys 中,
对于有些变量不需要在 cmcf->variables_keys中 也合法,如 http_ , sent_http_, upstream_http_, cookie_ , arg_ 开头的变量,
因为这些变量数量庞大且不可预知,
如 arg_, 当请求为 http://192.168.1.1/?pageid=2 则自动生成 $arg_pageid 变量.

ngx_http_variable_init_var() 不止检查合法性,还 对 cmcf->variables 的变量进行 赋值,即 get_handler , data, flags 字段。

ngx_http_variable_s 的个字段意义:
name 变量名
index 在 cmcf->variable 的下标
set_handler 目前只在使用set配置指令才用的上
下面三个字段 从 cmcf->variables_keys 拷贝值
flags 有两个值:
NGX_HTTP_VAR_CHANGEABLE ,表示变量是否可重复添加
比如有如下配置

set $file t_a;
set $file t_b;

若file变量被设置为 NGX_HTTP_VAR_CHANGEABLE , 那么 file 最终的值为 t_b,但若没有使用 NGX_HTTP_VAR_CHANGEABLE ,则ngx会提示 the duplicate "t_var" variable 然后退出

NGX_HTTP_VAR_NOCACHEABLE,表示变量是否可以缓存,

如$http_user_agent 变量,对于同一个连接,前面的请求和后面的请求,值都是一样的,所以可以只计算一次,之后用缓存的值。

data 表示存放变量值的地方,具体为 变量值 在 ngx_http_request_t 的偏移量。
我们知道 ngx的变量 通常是和 r 相关,对于直接相关(如 $http_user_agent 值在r内)的变量,可以直接从r中获得值,所以data记录 变量有效值在 ngx_http_request_t结构体中的偏移量。对于简介相关(如 $remote_port)的变量,r中不能直接获得值,所以data无效,通常设置为0。
如下

get_handler 获取变量值,通常配合 data字段,获得变量值
当变量值不能通过data直接获得,则使用 get_handler回调函数 进行处理。
如下

set_handler, 该回调目前只用于set指令,给用户提供 通过配置文件 修改 变量值的功能,
这些可以被set修改的变量一定是 NGX_HTTP_VAR_CHANGEABLE 并且 NGX_HTTP_VAR_NOCACHEABLE,
如下为 $args 的 set_handler()

检查并初始化完 cmcf->variables后, cmcf->variables_keys就没用了,可以释放空间

在每次处理请求时为变量值分配空间,变量和变量值一一对应,所以可以用 下标 找到变量值

ngx将变量值 和 变量属性 分开存放主要是为了节省空间

posted on 2022-03-17 17:28  开心种树  阅读(312)  评论(0编辑  收藏  举报