Sky25

nginx varible cache

This project is maintained by wangfakang

nginx 变量之坑

整过过程是这样的:在我的nginx模块里面会生成一个变量,然后这个变量的get_handler做的事情就是根据请求特征进行赋值该变量, 在nginx的配置文件中使用if指令判断该变量与某个常量进行比较,如下:

server {
    ...
    set $defaulet "0";
    ngx_ab $upstream $cookie_uid $defaulet;
    if ($upstream = "0") {
        set $a "0";
    }

    location /t {
        set $defaulet "1";
        ngx_ab $upstream $cookie_uid $defaulet;
        if ($upstream = "1") {
            set $a "1";
        }
    }

}

其中upstream这个变量是ngx_ab模块产生的一个变量,在server里面默认值被设置为0,在location里面默认值设置为1,然后一个请求 会触发ngx_ab模块的变量upstream取默认值,但是最终奇怪的是在location中输出的变量a竟然是0;

原因分析:

首先看看ngx_ab模块设置upstream这个变量的get_handler:

static ngx_int_t
ngx_http_ab_upstream_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
    uintptr_t data)
{
    ...
    v->valid = 1;
    v->no_cacheable = 0;   //此处就是罪魁祸首,表示此变量可以缓存
    v->not_found = 0;
    ...
}

然后在看看nginx的if指令取变量是如何取的,其核心代码如下:


ngx_http_variable_value_t *
ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
{
    ngx_http_variable_value_t  *v;

    v = &r->variables[index];

    if (v->valid || v->not_found) {
        if (!v->no_cacheable) {    //罪魁祸首,与其说罪魁祸首,还不如说是自己的无知
            return v;
        }

        v->valid = 0;
        v->not_found = 0;
    }

    return ngx_http_get_indexed_variable(r, index);
}

分析总结

总的来说,我们自己设置的变量设置了其可缓存属性,然后nginx的if指令在取该变量的时候会判断 该变量是否已经有值而且是否可以使用缓存中的值,若可以缓存则直接取上次计算出来的值。这也就是 为啥 在我的location中取到的upstream变量的值还是0的原因;

欢迎一起交流学习

在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流

Thx

Author