idevz/vanilla

全局变量Registry,并发请求的时候相互覆盖

hanwanhe opened this issue · 6 comments

idevz commented

Hi,@hanwanhe
Registry 这个表是所有请求共享的,这个没错,但是每次请求都会执行一个 init_vanilla 方法,这个方法会把每次请求的相关数据重置为当前请求的值,你可以看看这个函数:)
所以不会存在相互覆盖的现象,每个请求拿到的都是自己的。

那如果我要在controller直接用Registry这个变量呢?
qq 20170710180016
qq 20170710180034
qq 20170710180043

还有就是当我上面的两个url一起执行的时候,第一个请求的url是生成不了cache的,感觉像是第一个url的cache key被后面一个请求的cache key覆盖掉了。

cache key源码:
Registry['APP_PAGE_CACHE_KEY'] = Registry['REQ_URI'] .. ngx.encode_args(clean_args(Registry['REQ_ARGS_ARR']))

当一个请求没执行完,第二个请求执行的时候会把Registry全局变量修改掉,当第一个请求继续执行的时候,比如说要写cache了,但是Registry['APP_PAGE_CACHE_KEY']其实已经变成第二个请求的了。

idevz commented

Hi @hanwanhe 对于你的第一个问题,你可以直接用 Registry 这个变量,这个变量存在的意义在于 平凡对 ngx.varngx.req 表进行检索,会带来可观的性能消耗,所以这里把每次请求的相关数据缓存到了 Registry 表中,但是我并没有复现你两次请求 userid 不同导致的结果不一致的问题,请提供最小复现问题的代码包,我好细节看下问题所在。
对于第二个问题,page_cache 的 key 所依赖的 Registry['REQ_URI']Registry['REQ_ARGS_ARR'] 变量是每次请求都会被更新的,所以只要请求参数不同的两个请求是不会存在复写的问题,但是如果参数一致的两个请求,本来就该生成相同的 Key 去试图命中缓存。

function IndexController:index()
--return 'hello vanilla.'
ngx.sleep(10)
print_r(Registry['REQ_ARGS_ARR'])
return 'hello world'
end

这是我的代码,然后在配置文件中,把缓存去掉了,别的都是官方最新版刚安装完成的代码。
唯一要注意的点是要并发去请求不同的Url,当一个请求还没结束的时候,去请求下一个请求,然后第一请求的全局变量就被下一个请求覆盖了。

idevz commented

@hanwanhe 非常感谢你发现了这个bug,我已经修复了,你可以再试下:)
#104