• nginx 使用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

    这个 Lua 表可以用来存储基于请求的 Lua 环境数据,其生存周期与当前请求相同 (类似 Nginx 变量)。

    参考下面例子,

     location /test {
         rewrite_by_lua_block {
             ngx.ctx.foo = 76
         }
         access_by_lua_block {
             ngx.ctx.foo = ngx.ctx.foo + 3
         }
         content_by_lua_block {
             ngx.say(ngx.ctx.foo)
         }
     }
    

    访问 GET /test 输出

    79
    也就是说,ngx.ctx.foo 条目跨越一个请求的 rewrite (重写),access (访问),和 content (内容) 各处理阶段保持一致。

    每个请求,包括子请求,都有一份自己的 ngx.ctx 表。例如:

     location /sub {
         content_by_lua_block {
             ngx.say("sub pre: ", ngx.ctx.blah)
             ngx.ctx.blah = 32
             ngx.say("sub post: ", ngx.ctx.blah)
         }
     }
    
     location /main {
         content_by_lua_block {
             ngx.ctx.blah = 73
             ngx.say("main pre: ", ngx.ctx.blah)
             local res = ngx.location.capture("/sub")
             ngx.print(res.body)
             ngx.say("main post: ", ngx.ctx.blah)
         }
     }
    

    访问 GET /main 输出

    main pre: 73
    sub pre: nil
    sub post: 32
    main post: 73
    这里,在子请求中修改 ngx.ctx.blah 条目并不影响父请求中的同名条目,因为它们各自维护不同版本的 ngx.ctx.blah。

    内部重定向将摧毁原始请求中的 ngx.ctx 数据 (如果有),新请求将会有一个空白的 ngx.ctx 表。例如,

     location /new {
         content_by_lua_block {
             ngx.say(ngx.ctx.foo)
         }
     }
    
     location /orig {
         content_by_lua_block {
             ngx.ctx.foo = "hello"
             ngx.exec("/new")
         }
     }
    

    访问 GET /orig 将输出

    nil
    而不是原始的 "hello" 值。

    任意数据值,包括 Lua 闭包与嵌套表,都可以被插入这个“魔法”表,也允许注册自定义元方法。

    也可以将 ngx.ctx 覆盖为一个新 Lua 表,例如,

    ngx.ctx = { foo = 32, bar = 54 }
    当用在 init_worker_by_lua* 环境中,这个表与当前 Lua 句柄生命周期相同。

    ngx.ctx 表查询需要相对昂贵的元方法调用,这比通过用户自己的函数参数直接传递基于请求的数据要慢得多。所以不要为了节约用户函数参数而滥用此 API,因为它可能对性能有明显影响。

    而且由于元方法“魔法”,不要在 lua 模块级别试图使用 "local" 级别的 ngx.ctx ,例如 worker-level data sharing。下面示例是糟糕的:

    -- mymodule.lua
    local _M = {}

    -- 下面一行的 ngx.ctx 是属于单个请求的,但 ctx 变量是在 Lua 模块级别
    -- 并且属于单个 worker 的。

     local ctx = ngx.ctx
    
     function _M.main()
         ctx.foo = "bar"
     end
    
     return _M
    

    应使用下面方式替代:

     -- mymodule.lua
     local _M = {}
    
     function _M.main(ctx)
         ctx.foo = "bar"
     end
    
     return _M
    

    就是说,调用者对 ctx 表调用应通过函数传参方式完成。

  • 相关阅读:
    SQL SERVER2017 安装程序无法与下载服务器联系。无法安装机器学习服务的问题解决方式
    Kali Linux无法访问网络的问题
    Vue的冒泡事件
    记录阿里云ECS(Centos7.4)安装mysql 8.0.X服务
    沧桑巨变中焕发青春活力-记极1s HC5661A 打怪升级之路
    Asp.Net MVC过滤器小试牛刀
    C# Windows Service调用IBM Lotus Notes发送邮件
    记录一些js框架用途
    vc14(vs2015) 编译php7 记录
    C++ API方式连接mysql数据库实现增删改查
  • 原文地址:https://www.cnblogs.com/shenlinken/p/10156185.html
Copyright © 2020-2023  润新知