zoukankan      html  css  js  c++  java
  • ngx_lua配置及应用

    一、说明

    这里不对lua语言本身及其编译器运行环境等做介绍,以下所有介绍前提对lua相关有所了解。

    二、ngx_lua介绍

    原理

    ngx_lua将Lua嵌入Nginx,可以让Nginx执行Lua脚本,并且高并发、非阻塞的处理各种请求。Lua内建协程,这样就可以很好的将异步回调转换成顺序调用的形式。ngx_lua在Lua中进行的IO操作都会委托给Nginx的事件模型,从而实现非阻塞调用。开发者可以采用串行的方式编写程序,ngx_lua会自动的在进行阻塞的IO操作时中断,保存上下文;然后将IO操作委托给Nginx事件处理机制,在IO操作完成后,ngx_lua会恢复上下文,程序继续执行,这些操作都是对用户程序透明的。

    每个NginxWorker进程持有一个Lua解释器或者LuaJIT实例,被这个Worker处理的所有请求共享这个实例。每个请求的Context会被Lua轻量级的协程分割,从而保证各个请求是独立的。

    ngx_lua采用“one-coroutine-per-request”的处理模型,对于每个用户请求,ngx_lua会唤醒一个协程用于执行用户代码处理请求,当请求处理完成这个协程会被销毁。每个协程都有一个独立的全局环境(变量空间),继承于全局共享的、只读的“comman data”。所以,被用户代码注入全局空间的任何变量都不会影响其他请求的处理,并且这些变量在请求处理完成后会被释放,这样就保证所有的用户代码都运行在一个“sandbox”(沙箱),这个沙箱与请求具有相同的生命周期。

    得益于Lua协程的支持,ngx_lua在处理10000个并发请求时只需要很少的内存。根据测试,ngx_lua处理每个请求只需要2KB的内存,如果使用LuaJIT则会更少。所以ngx_lua非常适合用于实现可扩展的、高并发的服务。

    协程

    协程类似一种多线程,与多线程的区别有:

    1. 协程并非os线程,所以创建、切换开销比线程相对要小。
    2. 协程与线程一样有自己的栈、局部变量等,但是协程的栈是在用户进程空间模拟的,所以创建、切换开销很小。
    3. 多线程程序是多个线程并发执行,也就是说在一瞬间有多个控制流在执行。而协程强调的是一种多个协程间协作的关系,只有当一个协程主动放弃执行权,另一个协程才能获得执行权,所以在某一瞬间,多个协程间只有一个在运行。
    4. 由于多个协程时只有一个在运行,所以对于临界区的访问不需要加锁,而多线程的情况则必须加锁。
    5. 多线程程序由于有多个控制流,所以程序的行为不可控,而多个协程的执行是由开发者定义的所以是可控的。

    Nginx的每个Worker进程都是在epoll或kqueue这样的事件模型之上,封装成协程,每个请求都有一个协程进行处理。这正好与Lua内建协程的模型是一致的,所以即使ngx_lua需要执行Lua,相对C有一定的开销,但依然能保证高并发能力。

    二、ngx_lua安装

    Nginx中安装ngx_lua需要安装LuaJIT,ngx_devel_kit,ngx_lua等安装文件,我们这里用的OpenResty,内部已经集成ngx_lua,无需再安装任何模块。

    三、ngx_lua用法

    嵌套lua脚本

    location /lua {
    set $test "hello, world";
    content_by_lua '
        ngx.header.content_type = "text/plain";
        ngx.say(ngx.var.test);
    ';
    }

    $ curl 'http://134.32.28.134:8888/lua',输出 hello, world。

    include lua文件

    Nginx中include lua的脚本文件方式,如:

     location /mytest {    
          content_by_lua_file conf/alcache.lua;       
     }

    其中在alcache.lua中编写lua脚本即可。

    四、实际运用中通过lua结合分布式缓存对session的处理

    这里redis与memcache的支持不是调用Nginx自带redis与memcache模块,都是调用OpenResty内部集成的第三方模块

    nginx.conf部分配置

    location /login {    
        content_by_lua_file conf/alcache.lua;       
    }

    alcache.lua配置

    local key = tostring(ngx.var.arg_username)
    local val = tostring(ngx.var.arg_password)
    local passLogin = tostring(ngx.var.arg_passLoginFlag)
    local flags = tostring(ngx.var.arg_flags or 0)
    local exptime = tostring(ngx.var.arg_exptime or 0)
    local sessionId  = tostring(ngx.var.cookie_JSESSIONID)
    ngx.say("sessionId:",sessionId)
    ngx.say("key:",key)
    ngx.say("val:",val)
    if (key == nil and val == nil)  then return end
    --if (passLogin == nil or sessionId == nil)  then return end
    local memcached = require("resty.memcached")
    --local redis = require("resty.redis") 
    local cache,err = memcached:new()
    --local cache,err = redis.new()
    if not cache then
            ngx.say("failed to instantiate cache: ",err)
            return
    end
    cache:set_timeout(1000)
    local ok,err = cache:connect("134.32.28.134",11211)
    --local ok,err = cache:connect("134.32.28.134",6379)
    if not ok then
            ngx.say("failed to connect: ",err)
            return
    end
    local res,flags,err = cache:get(key)
    if err then
            ngx.say("failed to get ",key," : ",err)
            return
    end
    if res and tostring(res) ~= sessionId then
            cache:delete(key)
            cache:set(key,sessionId,exptime,flags)
    else
                    cache:set(key,sessionId,exptime,flags)
    end
    local ok, err = cache:close()  
                    if not ok then  
                ngx.say("failed to close:", err)  
            return  
    end
    local url = ngx.var.uri  
    local res = ngx.location.capture("/proxy")
  • 相关阅读:
    DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践
    UVA10071 Back to High School Physics
    UVA10071 Back to High School Physics
    UVA10055 Hashmat the Brave Warrior
    UVA10055 Hashmat the Brave Warrior
    UVA458 The Decoder
    UVA458 The Decoder
    HDU2054 A == B ?
    HDU2054 A == B ?
    POJ3414 Pots
  • 原文地址:https://www.cnblogs.com/jking10/p/5094055.html
Copyright © 2011-2022 走看看