《緩存利器》三、當前請求在各執行階段間的數據共享

在10.1節和10.2節,介紹的都是全局的緩存系統,那麼有沒有隻針對當前請求設置的緩存呢,即某個數據在請求的每個階段都有緩存,但請求結束緩存就會消失。

舉例來說,請求在rewrite階段生成1個緩存數據,作用是可以讓後面的階段(如content階段)獲取到該緩存數據,但該數據在請求完成後就沒有用了,可以在請求結束後清除掉。

這種緩存主要針對如下情況使用,在Ngx_Lua中Lua API的執行是有階段限制的,那麼當某個不能執行Lua API的階段需要使用Lua API指令生成數據時,就可以利用剛纔介紹的緩存方式,在其他階段處理好數據並緩存,在需要該數據的階段調用此緩存即可。這裏需要用到的緩存指令是ngx.ctx。

10.3.1 ngx.ctx的使用

ngx.ctx
環境:init_worker_by_lua、set_by_lua、rewrite_by_lua、access_by_lua、 content_by_lua、header_filter_by_lua、body_filter_by_lua、log_by_lua、ngx.timer.、balancer_by_lua
含義:ngx.ctx是Lua的table類型,用來緩存基於Lua的環境數據,該緩存在請求結束後會隨之清空,類似於Nginx中set指令的效果。
示例:

 rewrite_by_lua_block {
        --設置1個test數據
        ngx.ctx.test = 'nginx'
        ngx.ctx.test_1 = {a=1,b=2}

    }
    access_by_lua_block {
        --修改test
        ngx.ctx.test = ngx.ctx.test .. ' hello'
    }
    content_by_lua_block {
        --輸出test 和 test_1中的a元素的值
        ngx.say(ngx.ctx.test)
        ngx.say("a: ",ngx.ctx.test_1["a"])
    }
    header_filter_by_lua_block {
        --作爲響應頭輸出
        ngx.header["test"] = ngx.ctx.test .. ' world!'
    }
}

上述配置執行結果如下:

# curl -i  'http://testnginx.com/'
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Mon, 18 Jun 2018 05:07:15 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
test: nginx hello world!

nginx hello
a: 1

從執行結果可知,ngx.ctx的數據可以被Lua的每個執行階段讀/寫,並且支持存儲table類型的數據。

10.3.2 子請求和內部重定向的緩存區別

ngx.ctx在子請求和內部重定向中的使用方法有些區別。在子請求中修改ngx.ctx. 的數據不會影響主請求中ngx.ctx.對應的數據,它們維護的是不同的版本,如執行子請求的ngx.location.capture、ngx.location.capture_multi、echo_location等指令時;在內部重定向中修改數據會破壞原始請求中ngx.ctx.*的數據,新請求將會是1個空的ngx.ctx table,例如,當ngx.exec、rewrite配合last/break使用時。

ngx.ctx在內部重定向中使用的示例如下:

location /subq {
    header_filter_by_lua_block {
        --如果ngx.ctx.test不存在,則把not test賦值給a
        local a = ngx.ctx.test or 'not test'
        --作爲響應頭輸出
        ngx.header["test"] =  a .. ' world!'
    }
    content_by_lua_block {
        ngx.say(ngx.ctx.test)
    }
}
location / {
    header_filter_by_lua_block {
        ngx.header["test"] =  ' world!'
    }
    content_by_lua_block {
        ngx.ctx.test = "nginx"
        --執行內部重定向
        ngx.exec("/subq")
    }
}

執行結果如下:

# curl   -i 'http://testnginx.com/'
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Mon, 18 Jun 2018 05:36:38 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
test: not test world!

nil

從執行結果可知,ngx.ctx.test在內部重定向後變爲空。
注意:查詢ngx.ctx 會產生元方法調用,這會消耗一定的服務器資源,所以如果數據可以通過函數生成,就儘量不要使用ngx.ctx。如果希望更多地瞭解ngx.ctx對性能的影響,可以通過火焰圖對它的性能進行分析(詳見第16章)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章