一、说明

这里不对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")

ngx_lua配置及应用的更多相关文章

  1. nginx使用ngx_lua访问后端Thrift-Server实现和介绍

    背景 随着openresty的出现,让nginx使用lua解决一些业务的能力大幅度提高,ngx_lua可以使用nginx自生的基于事件驱动的IO模型,和后端的存储,业务等系统实现非阻塞的连接交互. 如 ...

  2. 使用ngx_lua构建高并发应用(1)

    转自:http://blog.csdn.net/chosen0ne/article/details/7304192 一. 概述 Nginx是一个高性能,支持高并发的,轻量级的web服务器.目前,Apa ...

  3. nginx插件ngx_lua

    ngx_lua是淘宝的维护的产品,真心不错.配置文件包含可以做很多事情的lua脚本. 公司有个产品对注册的广告盒子进行反向代理,这样可以在盒子上做很多事情:和服务器通信,远程控制盒子等等.nginx反 ...

  4. Nginx 配置指令的执行顺序(十)

    运行在 post-rewrite 阶段之后的是所谓的 preaccess 阶段.该阶段在 access 阶段之前执行,故名preaccess. 标准模块 ngx_limit_req 和 ngx_lim ...

  5. Nginx 配置指令的执行顺序(九)

    紧接在 server-rewrite 阶段后边的是 find-config 阶段.这个阶段并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心来完成当前请求与 location 配置块之间 ...

  6. Nginx 配置指令的执行顺序(五)

    Nginx 的 content 阶段是所有请求处理阶段中最为重要的一个,因为运行在这个阶段的配置指令一般都肩负着生成“内容”(content)并输出 HTTP 响应的使命.正因为其重要性,这个阶段的配 ...

  7. Nginx 配置指令的执行顺序(四)

    ngx_lua 模块提供了配置指令 access_by_lua,用于在 access 请求处理阶段插入用户 Lua 代码.这条指令运行于 access 阶段的末尾,因此总是在 allow 和 deny ...

  8. Nginx 配置指令的执行顺序(三)

    如前文所述,除非像 ngx_set_misc 模块那样使用特殊技术,其他模块的配置指令即使是在 rewrite 阶段运行,也不能和 ngx_rewrite 模块的指令混合使用.不妨来看几个这样的例子. ...

  9. Nginx 配置指令的执行顺序(二)

    我们前面已经知道,当 set 指令用在 location 配置块中时,都是在当前请求的 rewrite 阶段运行的.事实上,在此上下文中,ngx_rewrite 模块中的几乎全部指令,都运行在 rew ...

随机推荐

  1. mnist 手写数字识别

    mnist 手写数字识别三大步骤 1.定义分类模型2.训练模型3.评价模型 import tensorflow as tfimport input_datamnist = input_data.rea ...

  2. [转]QVector与QByteArray——Qt的写时复制(copy on write)技术

    我们在之前的博文QVector的内存分配策略与再谈QVector与std::vector——使用装饰者让std::vector支持连续赋值中简单聊了聊QVector内存分配和赋值方面的一点东西,今天接 ...

  3. 洛谷 P4592: bzoj 5338: [TJOI2018]异或

    题目传送门:洛谷P4592. 题意简述: 题面说的很清楚了. 题解: 发现没有修改很快乐.再看异或最大值操作,很容易想到可持久化 01trie. 这里要把 01trie 搬到树上,有点难受. 树剖太捞 ...

  4. 已知可生成0~4的rand5(),实现生成0~6的rand7()

    若已知生成0~6的rand7(),求生成0~4的rand5(),则一个方法就是不断生成0~7的数,直到这个数满足0~4就返回. int rand5(){ int res; do{ res = rand ...

  5. SQLServer数据操作(建库、建表以及数据的增删查改)[转]

    SQLSever数据操作   一.建立数据库:   create database DB ---数据库名称 (          name=data1 --文件名,          filename ...

  6. TF-tf.nn.dropout介绍

    官方的接口是这样的 tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None, name=None) 根据给出的keep_prob参数,将输入te ...

  7. 洛谷P2458 保安站岗

    传送门啦 分析: 树形dp刚刚入门,这是我做的第一个一个点同时受父亲节点和儿子节点控制的题目. 由于这个题中某一个点放不放保安与父亲和儿子都有关系(因为线段的两个端点嘛),所以我们做题时就要考虑全面. ...

  8. WinScp几个极大提高开发效率的小功能

    WinSCP 是一个 Windows 环境下使用 SSH 的开源图形化 SFTP 客户端.同时支持 SCP 协议.它的主要功能就是在本地与远程计算机间安全的复制文件. 最近研究了一下winscp的一些 ...

  9. 泛型 for to/in 遍历 PK 效率;TEnumerator、TEnumerable

    再使用泛型的时候,经常需要用到遍历功能: 只要继承了 TEnumerator 或 TEnumerable 这两个抽象类的 都具有遍历功能. 当然没有继承这两个抽象类的 也具有使用 for in 来遍历 ...

  10. javaweb作业一

    作业:Http全称叫什么?有什么特点?端口号是多少?超文本传输协议:(1)遵循请求/响应模型(2)http协议是一种无状态协议,请求/响应完成后,连接会断开.这时,服务器无法知道当前访问的用户是否是老 ...