Nginx配置及应用场景之lua
</div>
<div class="pt-article-main">
<div class="panel panel-default">
<div class="panel-body">
<div class="pt-article-content">
<h2 id="一说明">一、说明</h2>
这里不对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非常适合用于实现可扩展的、高并发的服务。
协程
协程类似一种多线程,与多线程的区别有:
- 协程并非os线程,所以创建、切换开销比线程相对要小。
- 协程与线程一样有自己的栈、局部变量等,但是协程的栈是在用户进程空间模拟的,所以创建、切换开销很小。
- 多线程程序是多个线程并发执行,也就是说在一瞬间有多个控制流在执行。而协程强调的是一种多个协程间协作的关系,只有当一个协程主动放弃执行权,另一个协程才能获得执行权,所以在某一瞬间,多个协程间只有一个在运行。
- 由于多个协程时只有一个在运行,所以对于临界区的访问不需要加锁,而多线程的情况则必须加锁。
- 多线程程序由于有多个控制流,所以程序的行为不可控,而多个协程的执行是由开发者定义的所以是可控的。
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 { <br/>
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")
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12" style="font-weight: 600">
<span>上一篇:
<a href="/blog/2013/10/22/nginx-3.html" title="Nginx配置及应用场景之高级配置" style="text-decoration: underline;">Nginx配置及应用场景之高级配置</a>
</span>
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12" style="font-weight: 600">
<span class="pull-right hidden-sm hiden-xs visible-lg visible-md">下一篇:
<a href="/blog/2014/01/15/apache-commons-beanutils.html" title="Apache Commons 系列简介 之 BeanUtils" style="text-decoration: underline;">Apache Commons 系列简介 之 BeanUtils</a>
</span>
<span class="hidden-lg hiden-md visible-sm visible-xs">下一篇:
<a href="/blog/2014/01/15/apache-commons-beanutils.html" title="Apache Commons 系列简介 之 BeanUtils" style="text-decoration: underline;">Apache Commons 系列简介 之 BeanUtils</a>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3 hidden-sm hidden-xs sidebar">
<div class="authorbar">
<div class="list-group" id="post-author">
<a href="/authors/tangshizhong/" class="list-group-item">
<span class="glyphicon glyphicon-user"></span>
作者:
汤仕忠
</a>
<a href="/authors/tangshizhong/" class="list-group-item">
<span class="glyphicon glyphicon-file"></span>
文章
<span class="pull-right badge">19</span>
<div class="inset-line"></div>
</a>
<a class="list-group-item">
<span class="glyphicon glyphicon-star"></span>
浏览量
<span class="pull-right badge">
</span>
<div class="inset-line"></div>
</a>
</div>
</div>
<div class="list-group" id="my-like">
<a href="" class="list-group-item">
<span class="glyphicon glyphicon-user"></span>
博文推荐
</a>
<a href="" class="list-group-item">
<object>
<a href="/blog/2018/06/20/first-bolg.html">
<span>Blog介绍</span>
</a>
</object>
<br/>
<span class="glyphicon glyphicon-user">
<object>
<a href="/authors/wfhuang/">黄文峰</a>
</object>
</span>
<span class="glyphicon glyphicon-calendar pull-right">2018.06.20</span>
<div class="inset-line"></div>
</a>
<a href="" class="list-group-item">
<object>
<a href="/blog/2018/06/08/spark-basic.html">
<span>Spark基础简易教程(Scala)</span>
</a>
</object>
<br/>
<span class="glyphicon glyphicon-user">
<object>
<a href="/authors/shenbin/">申斌</a>
</object>
</span>
<span class="glyphicon glyphicon-calendar pull-right">2018.06.08</span>
<div class="inset-line"></div>
</a>
<a href="" class="list-group-item">
<object>
<a href="/blog/2018/06/08/%E9%98%BF%E9%87%8C%E4%BA%91%E6%9C%8D%E5%8A%A1%E4%B8%8AElasticsearch%E7%9A%84%E5%AE%89%E8%A3%85%E5%8F%8A%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8-%E4%B8%89.html">
<span>阿里云服务上Elasticsearch的安装及简单使用(三)</span>
</a>
</object>
<br/>
<span class="glyphicon glyphicon-user">
<object>
<a href="/authors/chenlong/">陈龙</a>
</object>
</span>
<span class="glyphicon glyphicon-calendar pull-right">2018.06.08</span>
<div class="inset-line"></div>
</a>
<a href="" class="list-group-item">
<object>
<a href="/blog/2018/06/06/%E9%98%BF%E9%87%8C%E4%BA%91%E6%9C%8D%E5%8A%A1%E4%B8%8AElasticsearch%E7%9A%84%E5%AE%89%E8%A3%85%E5%8F%8A%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8-%E4%BA%8C.html">
<span>阿里云服务上Elasticsearch的安装及简单使用(二)</span>
</a>
</object>
<br/>
<span class="glyphicon glyphicon-user">
<object>
<a href="/authors/chenlong/">陈龙</a>
</object>
</span>
<span class="glyphicon glyphicon-calendar pull-right">2018.06.06</span>
<div class="inset-line"></div>
</a>
<a href="" class="list-group-item">
<object>
<a href="/blog/2018/06/05/%E9%98%BF%E9%87%8C%E4%BA%91%E6%9C%8D%E5%8A%A1%E4%B8%8AElasticsearch%E7%9A%84%E5%AE%89%E8%A3%85%E5%8F%8A%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8-%E4%B8%80.html">
<span>阿里云服务上Elasticsearch的安装及简单使用(一)</span>
</a>
</object>
<br/>
<span class="glyphicon glyphicon-user">
<object>
<a href="/authors/chenlong/">陈龙</a>
</object>
</span>
<span class="glyphicon glyphicon-calendar pull-right">2018.06.05</span>
<div class="inset-line"></div>
</a>
</div>
</div>