Ngx_Lua使用分享_linux error: ngx_http_lua_module requires the lua -程序员宅基地

技术标签: nginx  

1. Nginx_Lua

1.1. 介绍

ngx_lua – 把lua语言嵌入nginx中,使其支持lua来快速开发基于nginx下的业务逻辑

该模块不在nginx源码包中,需自行下载编译安装。使用lua 5.1(目前不支持lua 5.2) 或 luajit 2.0 。

添加lua支持后,开发复杂的模块,周期快,依然是100%异步非阻塞。

ngx_lua 哪些人在用:

淘宝、腾讯财经、网易财经、360、去哪儿网等

CloudFlare, CNN, Wingify, Reblaze, Turner, Broadcasting System

该项目主要开发者:

chaoslawful Taobao, Alibaba Grp.

agentzh CloudFlare

https://github.com/chaoslawful/lua-nginx-module

1.2. 安装

1.2.1. 安装JIT平台

JIT

通常,程序有两种运行方式:静态编译与动态直译。

静态编译的程序在执行前全部被翻译为机器码,而动态直译执行的则是一句一句边运行边翻译。

即时编译(Just-In-Time Compiler)则混合了这二者,一句一句编译源代码,但是会将翻译过的代码缓存起来以降低性能损耗。

JAVA、.NET 实现都使用即时编译以提供高速的代码执行。

注意:

在nginx.conf中添加"lua_code_cache on/off",来开启是否将代码缓存,所以每次变更"*.lua"文件时,必须reload nginx才可生效。

仅针对"set_by_lua_file, content_by_lua_file, rewrite_by_lua_file, and access_by_lua_file"有效, 因为其他为写在配置文件

中,更改代码也必须reload nginx。在生产环境下,不能禁用cache。同时在lua代码中使用"dofile" 或 "loadfie" 来加载外部lua脚步

将不会对它进行缓存,应该使用"require"来代替。禁用cache,当且仅当在调式代码下。

demo 1

LuaJIT

是一个利用JIT编译技术把Lua脚本直接编译成机器码由CPU运行

版本:2.0 与 2.1

当前稳定版本为 2.0。
2.1为版本与ngx_lua将有较大性能提升,主要是CloudFlare公司对luajit的捐赠。

FFI库,是LuaJIT中最重要的一个扩展库。
1. 它允许从纯Lua代码调用外部C函数,使用C数据结构;
2. 就不用再像Lua标准math库一样,编写Lua扩展库;
3. 把开发者从开发Lua扩展C库(语言/功能绑定库)的繁重工作中释放出来;

demo 2

下载编译

wget -c http://luajit.org/download/LuaJIT-2.0.2.tar.gz
tar xzvf LuaJIT-2.0.2.tar.gz
cd LuaJIT-2.0.2
make install PREFIX=/usr/local/luajit
echo "/usr/local/luajit/lib" > /etc/ld.so.conf.d/usr_local_luajit_lib.conf
ldconfig
#注意环境变量!
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0

1.2.2. NDK与Lua_module

NDK(Nginx Development Kit)模块是一个拓展Nginx服务器核心功能的模块

第三方模块开发可以基于它来快速实现

NDK提供函数和宏处理一些基本任务,减轻第三方模块开发的代码量。

wget -c https://github.com/simpl/ngx_devel_kit/archive/v0.2.18.tar.gz
wget -c https://github.com/chaoslawful/lua-nginx-module/archive/v0.8.6.tar.gz
tar xzvf v0.2.18
tar xzvf v0.8.6

1.2.3. 编译安装Nginx

wget -c http://nginx.org/download/nginx-1.4.2.tar.gz
tar xzvf nginx-1.4.2.tar.gz
cd nginx-1.4.2
./configure --add-module=../ngx_devel_kit-0.2.18/ --add-module=../lua-nginx-module-0.8.6/
make
make install

1.3. 嵌入Lua后

1.3.1. 检测版本

自己编译官方的 nginx 源码包,只需事前指定 LUAJIT_INC 和 LUAJIT_LIB 这两个环境变量。

验证你的 LuaJIT 是否生效,可以通过下面这个接口: 

location = /lua-version { 
	content_by_lua ' 
        	if jit then 
                	ngx.say(jit.version) 
            	else 
                	ngx.say(_VERSION) 
        	end 
        '; 
} 

demo 3

如果使用的是标准 Lua,访问 /lua-version 应当返回响应体 Lua 5.1
如果是 LuaJIT 则应当返回类似 LuaJIT 2.0.2 这样的输出。 
不要使用标准lua,应当使用luajit, 后者的效率比前者高多了。

也可以直接用 ldd 命令验证是否链了 libluajit-5.1 这样的 .so 文件,例如: 
[root@limq5 sbin]# ldd  nginx | grep lua
	libluajit-5.1.so.2 => /usr/local/luajit/lib/libluajit-5.1.so.2 (0x00007f48e408b000)
[root@limq5 sbin]#

1.3.2. Hello,World

在nginx.conf中的service添加一个location。

location = /test {
       content_by_lua '
           ngx.say("Hello World")
	   ngx.log(ngx.ERR, "err err err")
       ';
}

demo 4

用户访问 http://localhost/test 将会打印出“Hello World”内容。

ngx.say 是 lua 显露給模块的接口。

类似的有 ngx.log(ngx.DEBUG, “”),可以在error.log输出调试信息。

另外也可以调用外部脚本,如同我们写php、jsp应用时,业务脚本单独组织在.php或.jsp文件中一样

location = /test2 {
       content_by_lua_file conf/lua/hello.lua;
}

文件hello.lua内容如下:

ngx.say("Hello World")

这里的脚本可以任意复杂,也可以使用Lua 自己的库

lua可用模块列表:

http://luarocks.org/repositories/rocks/

安装类似yum,它也有一个仓库:

luarocks install luafilesystem

运行上面命令后,会编译一个 “lfs.so”, 文件,拷贝文件到nginx定义的LUA_PATH中,然后引用

该库,就可调用其中函数。

LUA_PATH:

lua_package_path ‘/opt/17173/nginx-ds/conf/lua/?.lua;;’

lua_package_cpath ‘/opt/17173/nginx-ds/conf/lua/lib/?.so;/usr/local/lib/?.?;;’;

其中”;;”代表原先查找范围。

demo 5

1.3.3. 同步形式,异步执行

我们假定,同时要访问多个数据源,而且,查询是没有依赖关系,那我们就可以同时发出请求

这样我总的延时, 是我所有请求中最慢的一个所用时间,而不是原先的所有请求用时的叠加

location = /api {
       content_by_lua '
           local res1, res2, res3 =
               ngx.location.capture_multi{
                   {"/memc"}, {"/mysql"}, {"/postgres"}
               }
           ngx.say(res1.body, res2.body, res3.body)
       ';
}

demo 6
ngx.location.capture 无法跨server进行处理, 只能在同一个server下的不同location。

1.4. Nginx与Lua执行顺序

1.4.1. Nginx顺序

Nginx 处理每一个用户请求时,都是按照若干个不同阶段(phase)依次处理的,而不是根据配置文件上的顺序。

Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是

post-read、server-rewrite、find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-files、content、log.

post-read:
读取请求内容阶段
Nginx读取并解析完请求头之后就立即开始运行
例如模块 ngx_realip 就在 post-read 阶段注册了处理程序,它的功能是迫使 Nginx 认为当前请求的来源地址是指定的某一个请求头的值。
server-rewrite
Server请求地址重写阶段
当 ngx_rewrite 模块的set配置指令直接书写在 server 配置块中时,基本上都是运行在 server-rewrite 阶段
find-config
配置查找阶段
这个阶段并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心来完成当前请求与 location 配置块之间的配对工作。
rewrite
Location请求地址重写阶段
当 ngx_rewrite 模块的指令用于 location 块中时,便是运行在这个 rewrite 阶段。
另外,ngx_set_misc(设置md5、encode_base64等) 模块的指令,还有 ngx_lua 模块的 set_by_lua 指令和 rewrite_by_lua 指令也在此阶段。
post-rewrite
请求地址重写提交阶段
由 Nginx 核心完成 rewrite 阶段所要求的“内部跳转”操作,如果 rewrite 阶段有此要求的话。
preaccess
访问权限检查准备阶段
标准模块 ngx_limit_req 和 ngx_limit_zone 就运行在此阶段,前者可以控制请求的访问频度,而后者可以限制访问的并发度。
access
访问权限检查阶段
标准模块 ngx_access、第三方模块 ngx_auth_request 以及第三方模块 ngx_lua 的 access_by_lua 指令就运行在这个阶段。
配置指令多是执行访问控制性质的任务,比如检查用户的访问权限,检查用户的来源 IP 地址是否合法
post-access
访问权限检查提交阶段
主要用于配合 access 阶段实现标准 ngx_http_core 模块提供的配置指令 satisfy 的功能。
satisfy all(与关系)
satisfy any(或关系)
try-files
配置项try_files处理阶段
专门用于实现标准配置指令 try_files 的功能
如果前 N-1 个参数所对应的文件系统对象都不存在,try-files 阶段就会立即发起“内部跳转”到最后一个参数(即第 N 个参数)所指定的 URI.
content
内容产生阶段
Nginx 的 content 阶段是所有请求处理阶段中最为重要的一个,因为运行在这个阶段的配置指令一般都肩负着生成“内容”
并输出 HTTP 响应的使命。
log
日志模块处理阶段
记录日志

淘宝有开放一个nginx开发手册,里面包含很多有用的资料

http://tengine.taobao.org/book/

作者的google论坛:

https://groups.google.com/forum/#!forum/openresty

1.4.2. Lua顺序

Nginx下Lua处理阶段与使用范围:

init_by_lua            http
set_by_lua             server, server if, location, location if
rewrite_by_lua         http, server, location, location if
access_by_lua          http, server, location, location if
content_by_lua         location, location if
header_filter_by_lua   http, server, location, location if
body_filter_by_lua     http, server, location, location if
log_by_lua             http, server, location, location if
timer
init_by_lua:
在nginx重新加载配置文件时,运行里面lua脚本,常用于全局变量的申请。
例如lua_shared_dict共享内存的申请,只有当nginx重起后,共享内存数据才清空,这常用于统计。

set_by_lua:
设置一个变量,常用与计算一个逻辑,然后返回结果
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API

rewrite_by_lua:
在access阶段前运行,主要用于rewrite

access_by_lua:
主要用于访问控制,能收集到大部分变量,类似status需要在log阶段才有。
这条指令运行于nginx access阶段的末尾,因此总是在 allow 和 deny 这样的指令之后运行,虽然它们同属 access 阶段。

content_by_lua:
阶段是所有请求处理阶段中最为重要的一个,运行在这个阶段的配置指令一般都肩负着生成内容(content)并输出HTTP响应。

header_filter_by_lua:
一般只用于设置Cookie和Headers等
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API

body_filter_by_lua:
一般会在一次请求中被调用多次, 因为这是实现基于 HTTP 1.1 chunked 编码的所谓“流式输出”的。
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API

log_by_lua:
该阶段总是运行在请求结束的时候,用于请求的后续操作,如在共享内存中进行统计数据,如果要高精确的数据统计,应该使用body_filter_by_lua。
该阶段不能运行Output API、Control API、Subrequest API、Cosocket API

timer:

可参考官方文档:

http://wiki.nginx.org/HttpLuaModule

2. Lua基本语法

2.1. 关键字

and	break	do	else	elseif	
end	false	for	function	if	
in	local	nil	not	or	
repeat	return	then	true	until	while

2.2. 运算

2.2.1. 数字运算

支持 +, -, *, /,^  比如2^3 结果为8, 2^4结果为16。
连接两个字符串,用".."运处符, php为".", JAVA、C#为"+"

2.2.2. 赋值运算

a,b,c,d=1,2,3,4   -- 多变量一起赋值
a,b=b,a  --交换变量功能
在默认情况下,变量总是认为是全局的。假如需要定义局部变量,则在第一次赋值的时候,需要用local说明。比如:
local a,b,c = 1,2,3  -- a,b,c都是局部变量

2.2.3. 逻辑运算

and, or, not
在Lua中,只有false和nil才计算为false,其它任何数据都计算为true,0也是true
and 和 or的运算结果不是true和false,而是和它的两个操作数相关。

a and b:如果a为false,则返回a;a true 返回b
a or b:如果 a 为true,则返回a;a false 返回b
模拟C语言中的语句:x = a? b : c,在Lua中,可以写成:x = a and b or c。
最有用的语句是: x = x or v,它相当于:if not x then x = v end 。

2.3. 条件判断语句

2.3.1. if

if 条件 then 
      ... 
elseif 条件 then
      ... else ... 
end

2.3.2. repeat

repeat ... until 条件

2.3.3. while

while 条件 
do 
      ... 
end

2.3.4. for

for 变量=初值, 终点值, 步进 
do
      ... 
end
for 变量1, 变量2, ... 变量n in 表或枚举函数 
do 
       ... 
end

2.4. 常用结构

2.4.1. table

1. table 是 lua 中最重要的数据类型。
2. table 类似于 python 中的字典。
3. table 只能通过构造式来创建

;例1

Lua代码
tab = { a = 10, b = 20, c = 30, d = 40 }  
print(tab["a"])  

注释: 
1)table 中的每项要求是 key = value 的形式 
2)key 只能是字符串, 这里的 a, b, c, d 都是字符串,但是不能加上引号 
3)通过 key 来访问 table 的值,这时候, a 必须加上引号

;例2

tab = { 10, m = 20, 11, 12, 13 }  

print(tab[1])  = 10
print(tab[2])  = 11
print(tab[3])  = 12
print(tab[4])  = 13

获取表长度:
print(table.getn(tab))  -> 4
print(#tab)             -> 4

遍历表:
for k, v in pairs(tab) do
	print(k, ":", v)
end

1	:	10
2	:	11
3	:	12
4	:	13
m	:	20

注释:
1)省略key,会自动以1开始编号,并跳过设置过的key
2)获取表长度,只有当表使用1自动编号开始,可以获取

2.4.2. lua表空判断

在项目的脚本lua中经常有这样的需求

local a = {}
判断表a是否为空,有提供api table.maxn(a) 或 #a 获取表a长度,但是该情况只
针对key为数字且安装递增方式。

对于自定义key的情况下,获取表长度将会失败,可通过lua内置 next函数解决该问题。

2.5. 参考

lua官方手册        http://www.lua.org/manual/5.1/
lua中文翻译手册    http://www.codingnow.com/2000/download/lua_manual.html
转载:http://17173ops.com/2013/11/01/17173-ngx-lua-manual.shtml
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiaofei0859/article/details/70474191

智能推荐

计算机丢失concrt140,小编教你解决concrt140 dll 【解决教程】 的技巧_-程序员宅基地

文章浏览阅读4.5w次。近日有小伙伴发现电脑出现问题了,在突然遇到concrt140 dll时不知所措了,对于concrt140 dll带来的问题,其实很好解决concrt140 dll带来的问题,下面小编跟大家介绍concrt140 dll解决方法:丢失CONCRT140.dll,怎么办?答:分析及解决:网上下载这个DLL文件,将其放置到system32目录下面。 重启系统,或者在CMD下面运行regsvr32*.dl..._concrt140.dll下载教程

微信小程序源码案例大全_微信小程序switch页面demo-程序员宅基地

文章浏览阅读4.3k次,点赞4次,收藏62次。微信小程序demo:足球,赛事分析 小程序简易导航 小程序demo:办公审批 小程序Demo:电魔方 小程序demo:借阅伴侣 微信小程序demo:投票 微信小程序demo:健康生活 小程序demo:文章列表demo 微商城(含微信小程序)完整源码+配置指南 微信小程序Demo:一个简单的工作系统 微信小程序Demo:用于聚会的小程序 微信小程序Demo:Growth 是一款..._微信小程序switch页面demo

SLAM学习笔记(Code2)----刚体运动、Eigen库_eigen.determinant-程序员宅基地

文章浏览阅读2.2k次。2.1除了#include<iostream>之外的头文件#include <Eigen/Core>//Core:核心#include <Eigen/Dense>//求矩阵的逆、特征值、行列式等#include <Eigen/Geometry>//Eigen的几何模块,可以利用矩阵完成如旋转、平移/***其他***/#include <ctime>//可用于计时,比较哪个程序更快#include <cmath>//包含a_eigen.determinant

图像梯度-sobel算子-程序员宅基地

文章浏览阅读1w次,点赞12次,收藏61次。(1)理论部分x 水平方向的梯度, 其实也就是右边 - 左边,有的权重为1,有的为2 。若是计算出来的值很大 说明是一个边界 。y 竖直方向的梯度,其实也就是下面减上面,权重1,或2 。若是计算出来的值很大 说明是一个边界 。图像的梯度为:有时简化为:即:(2)程序部分函数:Sobelddepth 通常取 -1,但是会导致结果溢出,检测不出边缘,故使..._sobel算子

cuda10.1和cudnn7.6.5百度网盘下载链接(Linux版)_cudnn7.6网盘下载-程序员宅基地

文章浏览阅读3.6k次,点赞17次,收藏8次。cuda10.1和cudnn7.6.5百度网盘下载链接(Linux版)在官网下载不仅慢,,,主要是还总失败。。终于下载成功了,这里给出百度网盘下载链接,希望可以帮到别人百度网盘下载链接提取码: vyg5_cudnn7.6网盘下载

Python正则表达式大全-程序员宅基地

文章浏览阅读9.3w次,点赞69次,收藏427次。定义:正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。上面都是官方的说明,我自己的理解是(仅供参考):通过事先规定好一些特殊字符的匹配规则,然后利用这些字符进行组合来匹配各种复杂的字符串场景。比如现在的爬虫和数据分析,字符串校验等等都需要用_python正则表达式

随便推点

NILM(非侵入式电力负荷监测)学习笔记 —— 准备工作(一)配置环境NILMTK Toolkit_nilmtk学习-程序员宅基地

文章浏览阅读1.9w次,点赞27次,收藏122次。安装Anaconda,Python,pycharm我另一篇文章里面有介绍https://blog.csdn.net/wwb1990/article/details/103883775安装NILMTK有了上面的环境,接下来进入正题。NILMTK官网:http://nilmtk.github.io/因为官方安装流程是基于linux的(官方安装流程),我这里提供windows..._nilmtk学习

k8s-pod 控制器-程序员宅基地

文章浏览阅读826次,点赞20次,收藏28次。如果实际 Pod 数量比指定的多那就结束掉多余的,如果实际数量比指定的少就新启动一些Pod,当 Pod 失败、被删除或者挂掉后,RC 都会去自动创建新的 Pod 来保证副本数量,所以即使只有一个 Pod,我们也应该使用 RC 来管理我们的 Pod。label 与 selector 配合,可以实现对象的“关联”,“Pod 控制器” 与 Pod 是相关联的 —— “Pod 控制器”依赖于 Pod,可以给 Pod 设置 label,然后给“控制器”设置对应的 selector,这就实现了对象的关联。

相关工具设置-程序员宅基地

文章浏览阅读57次。1. ultraEdit设置禁止自动更新: 菜单栏:高级->配置->应用程序布局->其他 取消勾选“自动检查更新”2.xshell 传输文件中设置编码,防止乱码: 文件 -- 属性 -- 选项 -- 连接 -- 使用UTF-8编码3.乱码修改:修改tomcat下配置中,修改: <Connector connectionTimeou..._高级-配置-应用程序布局

ico引入方法_arco的ico怎么导入-程序员宅基地

文章浏览阅读1.2k次。打开下面的网站后,挑选要使用的,https://icomoon.io/app/#/select/image下载后 解压 ,先把fonts里面的文件复制到项目fonts文件夹中去,然后打开其中的style.css文件找到类似下面的代码@font-face {font-family: ‘icomoon’;src: url(’…/fonts/icomoon.eot?r069d6’);s..._arco的ico怎么导入

Microsoft Visual Studio 2010(VS2010)正式版 CDKEY_visual_studio_2010_professional key-程序员宅基地

文章浏览阅读1.9k次。Microsoft Visual Studio 2010(VS2010)正式版 CDKEY / SN:YCFHQ-9DWCY-DKV88-T2TMH-G7BHP企业版、旗舰版都适用推荐直接下载电驴资源的vs旗舰版然后安装,好用方便且省时!) MSDN VS2010 Ultimate 简体中文正式旗舰版破解版下载(附序列号) visual studio 2010正_visual_studio_2010_professional key

互联网医疗的定义及架构-程序员宅基地

文章浏览阅读3.2k次,点赞2次,收藏17次。导读:互联网医疗是指综合利用大数据、云计算等信息技术使得传统医疗产业与互联网、物联网、人工智能等技术应用紧密集合,形成诊前咨询、诊中诊疗、诊后康复保健、慢性病管理、健康预防等大健康生态深度..._线上医疗的定义