目录

Lua脚本简述

Lua脚本简述

脚本特点

安装Lua

lua小例子

Nginx增加Lua执行模块

Nginx嵌入Lua脚本语言

Nginx嵌入Lua脚本语言

ngx_lua支持的指令

在OpenResty中演示ngx_lua的指令

打造高性能后端接口

OpenResty Redis模块

OpenResty mysql模块

OpenResty http模块

Lua模板渲染器

使用

Nginx非阻塞与Lua协程的绝配

Lua协程

Nginx的API生成页面


Lua脚本简述

nginx三大核心功能,包含静态资源、反向代理、api模块扩展,对于lua脚本的扩展,就是api模块扩展的一部分;并且nginx可以通过lua脚本直接调用redis服务器;

Lua脚本简述

lua官网:

The Programming Language Lua

Lua是一种功能强大,高效,轻量级,可嵌入的脚本语言,非常容易嵌入
到我们应用程序中。
Lua是动态类型的,通过使用基于寄存器的虚拟机解释字节码来运行,并
具有增量垃圾收集的自动内存管理,使其成为配置,脚本和快速原型设计
的理想选择。
Lua旨在成为一种轻量级可嵌入脚本语言。它用于各种应用程序,从游戏
到Web应用程序和图像处理。
Lua 将简单的程序语法与基于关联阵列和可扩展语义的强大数据描述构造相结合。Lua 采用动态键入,通过基于注册的虚拟计算机解释字形码进行运行,并具有自动内存管理,可增加垃圾收集,非常适合配置、脚本和快速原型制作。

应用在图像处理这些。

应用场景
  • 1. 许多工业应用 (例如, Adobe的Photoshop Lightroom)
  • 2. 重点是嵌入式系统(例如, 巴西的数字电视的 Ginga中间件)
  • 3. Lua目前 是游戏中领先的脚本语言,在游戏 (例如, 魔兽世界和愤怒的小鸟)中使用。

脚本特点

  • Lua是解释脚本语言领域中最快的语言。
  • Lua是便携式的,在具有标准C编译器的所有平台中构建成开箱即用,可运行各种Unix和Windows, 移动设备(运行Android,iOS,BREW,Symbian,Windows Phone),嵌入式微处理器(如ARM和Rabbit,适用于Lego MindStorms等应用程序),IBM大型机等。
  • 可嵌入,Lua是一种快速语言引擎,占用空间小,可以轻松嵌入到应用程序中。
  • 简单而强大,提供实现功能的*元机制*,而不是直接在语言中提供大量功能。Lua不是纯粹的面对 象语言,提供了实现类和继承的元机制。
  • ,源包含大约24000行C,包含源代码和文档的Lua 5.3.5的tar包需要297K压缩和1.2M未压缩。 免费,MIT许可证,可以用于任何目的,包括商业目的,完全免费。

比js语言更加广泛。轻量级语言不能做的事情,没有什么大的框架,例如java中spring,这也是它其中的一个缺点把

安装Lua

比较简单

curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz
tar zxf lua-5.3.5.tar.gz
cd lua-5.3.5
make linux test

依赖不多,直接下载就行。

使用打印 hello world

$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print("hello, world")
hello, world

lua小例子

新建mydata.lua文件
  • 定义一个外界可见的表
  • 受保护的自定义数据内容
  • function给_M定义一个方法,get_age,用来返回data中的数据
  • 向外界暴露表
-- 定义一个外界可见的表
local _M = {}-- 受保护的自定义数据内容
local data = {dog = 5,cat = 3,pig = 1,
}-- function给_M定义一个方法,get_age,用来返回data中的数据
function _M.get_age(name)return data[name]
end -- end表示方法结束-- 向外界暴露表
return _M

这个和js中的方法就很像了。

利用lua脚本实现 阶乘

-- defines a factorial function
function fact (n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
print("enter a number:")
a = io.read("*number") -- read a number
print(fact(a))

要运行 ,直接 使用 lua 文件就能运行起来

语法比Java要简略,缩进对齐,无大括号分号

Nginx增加Lua执行模块

Nginx嵌入Lua脚本语言

ngx_lua模块

不鼓励自己用Nginx构建这个模块,自己构建需要注意,Nginx,LuaJIT和OpenSSL官方发行版具有各种限制和长期
存在的错误,这些错误可能会导致某些模块的功能被禁用,无法正常运行或运行速度变慢。如何编译,参考 《Nginx嵌入Lua脚本语言操作》手册。
使用ngx_lua模块相当于使用Openresty,建议用官方版本OpenResty,它做了大量优化、集成了常用的第三方插件。
OpenResty
OpenResty内部集成了大量精良的 Lua 库、第三方模块以及 大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。OpenResty是一款基于
NGINX 和 LuaJIT 的Web 平台。OpenResty的安装参考《OpenResty安装操作》,比构建ngx_lua模块简单很多.
openresty/lua-nginx-module: Embed the Power of Lua into NGINX HTTP servers (github.com)
OpenResty安装操作 提取码:ppa8

Nginx嵌入Lua脚本语言

安装编译Nginx

  • 安装依赖项
yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel# lua_jit
wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz
tar -xvf LuaJIT-2.0.5.tar.gz
cd LuaJIT-2.0.5
make install

下载安装nginx和依赖项

cd ~
# nginx
wget http://nginx.org/download/nginx-1.14.2.tar.gz
tar -xvf nginx-1.14.2.tar.gz
# ndk
wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.0.zip
unzip v0.3.0.zip
# ngx_lua 模块
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.14.zip
unzip v0.10.14.zip# 安装nginx
cd nginx-1.14.2
./configure --prefix=/usr/local/nginx-1.14.2 \--add-module=../ngx_devel_kit-0.3.0 \--add-module=../lua-nginx-module-0.10.14
  • 测试lua模块是否安装成功
  • 创建一个文件夹存储lua脚本
mkdir /usr/local/nginx-1.14.2/lua_scripts
  • 创建mydata.lua
-- mydata.lualocal _M = {}local data = {dog = 3,cat = 4,pig = 5,}function _M.get_age(name)return data[name]endreturn _M
  • nginx.conf文件
 lua_package_path "/usr/local/nginx-1.14.2/lua_scripts/?.lua;;";server {...location /lua {content_by_lua_block {local mydata = require "mydata"ngx.say(mydata.get_age("dog"))}}

可能的错误

# 1、动态库找不到
./sbin/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory
# 解决办法:
echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
ldconfig# 2、warn提示
nginx: [alert] detected a LuaJIT version which is not OpenResty's; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html)
# 告诉你,你不要用这个luajit版本,可以用openresty提供的luajit优化版本,或者干脆直接用openresty

安装lua_redis

wget https://codeload.github.com/openresty/lua-resty-redis/zip/master
unzip master
cd lua-resty-redis-master
make && make install

都是lua集成的组件。

OpenResty 目录

包括nginx目录等。

ngx_lua支持的指令

指令分为配置指令、控制指令。
控制指令分为两种方式:
lua脚本块*_by_lua_block
lua脚本文件*_by_lua_file
Lua脚本执行顺序,如右图从上至下:初始化、重写/访问、内容处理、日志输出四个阶段。
内容处理可以由上游服务或者Lua脚本语言来处理,用Lua脚本就大有可为了。

在OpenResty中演示ngx_lua的指令

设置由set_by_lua,content_by_lua等指定的脚本使用的Lua模块搜索路径。类似java的classPath

预加载json模块

在location、location if上下文中使用。充当“内容处理程序”并执行指定的lua脚本内容,Lua代码可以进行API调用,并在独立的全局环境(即沙箱)中作为新的衍生协程执行

worker_processes  1;
events {worker_connections 1024;
}http {# 设置由set_by_lua, content_by_lua等指定的脚本使用的Lua模块搜索路径。类似java的classPath# 路径字符串采用标准的Lua路径形式,;; 可用于代表原始搜索路径。lua_package_path "/usr/local/openresty/lua_scripts/?.lua;;";# 申请一个名为dogs的10m字典内存,共享在所有工作进程中lua_shared_dict dogs 10m;# 在服务器启动时预加载Lua模块,并利用现代操作系统的写时复制(COW)优化。init_by_lua_block {-- 预加载json模块require "cjson"-- 操作共享内存local dogs = ngx.shared.dogs;dogs:set("Tom", 56)}server {listen 8080;location /lua {default_type text/html;# 在location、location if上下文中使用。充当“内容处理程序”并执行指定的lua脚本内容,# Lua代码可以进行API调用,并在独立的全局环境(即沙箱)中作为新的衍生协程执行content_by_lua_block {local mydata = require "mydata"ngx.say(mydata.get_age("dog"))-- require关键字会返回init_by_lua_block中已经预加载了cjson模块ngx.say(require "cjson".encode{dog = 5, cat = 6})-- 读取共享内存中的信息local dogs = ngx.shared.dogs;ngx.say(dogs:get("Tom"))}}}
}

在运行的时候,需要去掉 nginx目录在运行

打造高性能后端接口

OpenResty Redis模块

OpenResty中默认嵌入了下列模块,包含Redis,所以要使用Redis非常简单。

要使用Redis非常简单

-- 引入Redis模块
local redis = require("resty.redis")
--创建实例
local red = redis:new()
--建立连接
local ok, err = red:connect(“127.0.0.1”, 6379)
--调用API进行处理
ok, err = red:set("msg", "hello world")
local resp, err = red:get("msg")

这里 用local进行申请变量。 这是lua脚本 和js语言基本一致的地方。

这个模块要保证在linux上客户端存在redis,然后运行lua脚本。

OpenResty  中 lualib /resty 中放在 这个目录下面的

  • 在写lua脚本时需要引用  默认就是 lualib
local redis = require("resty.redis")  
  • 创建实例  建立连接,通过new方式
--创建实例
local red = redis:new()
--设置超时(毫秒)
red:set_timeout(1000)
--建立连接
local ip = "127.0.0.1"
local port = 6379
local ok, err = red:connect(ip, port)  
  • 发送数据并判断是否成功
if not ok then  ngx.say("connect to redis error : ", err)  return close_redis(red)
end
--调用API进行处理
ok, err = red:set("msg", "hello world")
if not ok then  ngx.say("set msg error : ", err)  return close_redis(red)
end  
  • 关闭redis
local function close_redis(red)  if not red then  return  end  --释放连接(Redis连接池实现)local pool_max_idle_time = 10000 --毫秒  local pool_size = 100 --连接池大小  local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)  if not ok thenngx.say("set keepalive error : ", err)end
end 
  • 得到的数据为空处理
--得到的数据为空处理
if resp == ngx.null then  resp = ''  --比如默认值
end
ngx.say("msg : ", resp)  close_redis(red) 

对于redis操作,lua脚本是没有事务的支持的。

在 nginx_lua_lib.conf配置上对应的location

请求得到数据

 使用场景 

降低tomcat的压力,非常有用的。根据不会走到web服务器上。 增大请求这些,是构建百万连接的重要一部分

OpenResty mysql模块

也是一样的 加载 mysql的驱动

local mysql = require("resty.mysql")

创建实例

 local db, err = mysql:new()  if not db then  ngx.say("new mysql error : ", err)  return  end  

设置超时时间(毫秒)

 db:set_timeout(1000)

配置建立连接

 local props = {  host = "127.0.0.1",  port = 3306,  database = "mysql",  user = "root",  password = "123456"  }  local res, err, errno, sqlstate = db:connect(props)  if not res then  ngx.say("connect to mysql error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  return close_db(db)  end  

删除表

 local drop_table_sql = "drop table if exists test"  res, err, errno, sqlstate = db:query(drop_table_sql)  if not res then  ngx.say("drop table error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  return close_db(db)  end  

创建表

 local create_table_sql = "create table test(id int primary key auto_increment, ch varchar(100))"  res, err, errno, sqlstate = db:query(create_table_sql)  if not res then  ngx.say("create table error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  return close_db(db)  end  

关闭连接

    local function close_db(db)  if not db then  return  end  db:close()  end  

这里有个点安全机制,防止sql注入

--防止sql注入  local ch_param = ngx.req.get_uri_args()["ch"] or ''  --使用ngx.quote_sql_str防止sql注入  local query_sql = "select id, ch from test where ch = " .. ngx.quote_sql_str(ch_param)  res, err, errno, sqlstate = db:query(query_sql)  if not res then  ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  return close_db(db)  end  for i, row in ipairs(res) do  for name, value in pairs(row) do  ngx.say("select row ", i, " : ", name, " = ", value, "<br/>")  end  end  

OpenResty http模块

OpenResty默认没有提供Http客户端,需要使用第三方提供,从github上搜索相应的客户端,比如lua-resty-http

cd /usr/local/openresty/lualib/resty/
sudo wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua
sudo wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua

这个模块可以调用第三方的服务。

local http = require("resty.http")
--创建http客户端实例
local httpc = http.new()local resp, err = httpc:request_uri("http://www.baidu.com", {  method = "GET",  path = "/s?wd=123",headers = {["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"  }
})  if not resp then  ngx.say("request error :", err)  return
end  --获取状态码
ngx.status = resp.status  --获取响应头
for k, v in pairs(resp.headers) do  if k ~= "Transfer-Encoding" and k ~= "Connection" then  ngx.header[k] = v  end
end
--响应体
ngx.say(resp.body)httpc:close()  

Lua模板渲染器

动态web网页开发是Web开发中一个常见的场景,Lua中也有许多模板引擎,我们通过lua-resty-template来完成动态页面的渲染。

cd /usr/local/openresty/lualib/resty/
wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template.lua
mkdir /usr/local/openresty/lualib/resty/html
cd /usr/local/openresty/lualib/resty/html
wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template/html.lua

动态生成网页模板。

使用

nginx配置文件,添加模板解析路径

#首先匹配nginx下面的模板目录
set $template_location "/templates";
#然后匹配指定的模板根目录,我们这里是/usr/local/openresty/lua_scripts
set $template_root "/usr/local/openresty/lua_scripts";
#或者通过root指令来切换路径
root /usr/local/openresty/lua_scripts;

lua内容,html_template.lua

local template = require("resty.template")  local context = {  title = "lua模板渲染",  name = "hash同学",  description = "<script>alert(1);</script>",  age = 20,  hobby = {"电影", "音乐", "阅读"},  score = {语文 = 90, 数学 = 80, 英语 = 70},  score2 = {  {name = "语文", score = 90},  {name = "数学", score = 80},  {name = "英语", score = 70},  }
}
template.render("resty_template.html", context)

进行解析生成模板。

Nginx非阻塞与Lua协程的绝配

服务器有个设计原则:永远不能阻塞。
nginx作为非常优秀的服务器,这点发挥的非常极致。在nginx里有很多的体现异步的地方。
Lua嵌入会阻塞吗?
-- foo本身是个协程,由nginx调用
function foo()
-- 此处由nginx发起db的连接请求,因为异步这里先暂停协程
users = db.query('users', {name: name});
-- 当请求有响应得到处理时,继续执行协程,这些才运行
deal_with(users);
end
通过nginx的异步机制和lua的协程,很容易实现这种同步写法,异步实现的模型,但对开发人
员而言,不用关心内部做了什么。

Lua协程

什么是协程?
Lua协程,称为协作式多线程。Lua中的协程代表一个独立的执行线程,具有自己的堆栈、自己的局部变量、PC计数器和其自
己的指令指针; 与java线程不同的是,协程只通过显式调用yield函数来暂停其执行。同一时间,多协程只运行其中一个,java多线程则可以运行多个。
协程可以处于三种不同状态之一:暂停,运行和死亡
使用Lua协程

coroutine.create(f)
创建一个新的协同程序并返回一个类型为thread的对象,并不启动协程。
coroutine.resume(co)
开始或继续执行协同程序co
coroutine.yield
暂停执行调用协程,让出CPU
coroutine.wrap(f)
类似create方法,创建一个协程但它不是返回协程本身,而是返回一个函数,当被调用时,它恢复协程

Nginx的API生成页面

可以通过Nginx的API服务功能来实现商品页面功能设计
将需要的数据准备好,通过Lua访问Redis获取得,再由Lua生成json数据,交给Lua模板解析器,
通过Lua模板解析器,来完成模板数据的动态生成。

达到对一个商品页面的实现。

Nginx框架之Lua拓展相关推荐

  1. CentOS6.4 安装OpenResty和Redis 并在Nginx中利用lua简单读取Redis数据

    1.下载OpenResty和Redis OpenResty下载地址:wget http://openresty.org/download/ngx_openresty-1.4.3.6.tar.gz Re ...

  2. nginx整合php+lua+oracle环境搭建

    nginx整合php+lua+oracle环境搭建 标签: nginxluaoraclephplinux 2014-09-25 10:39 1473人阅读 评论(0) 收藏 举报  分类:   技术( ...

  3. Linux守护进程的创建(结合nginx框架)

    Linux守护进程的创建(结合nginx框架) 先介绍几个相关函数: int dup2(arg1,arg2):参数一指向的内容赋给参数二,shi的参数二也能访问参数一所指向的内容,并返回新的描述符 i ...

  4. 无线专题 openwrt feeds、web框架luci(lua语言)、UCI (统一配置接口)

    1.openwrt feeds UCI (统一配置接口)openwrt官方说明(有中文版本):https://oldwiki.archive.openwrt.org/zh-cn/doc/uci 在Op ...

  5. Nginx安装配置Lua支持

    Nginx安装配置Lua支持 1. 环境准备 2. 下载最新的`luajit`和`ngx_devel_kit`以及`lua-nginx-module`解压 3. 解压`ngx_devel_kit`以及 ...

  6. nginx lua连接mysql_OpenResty的安装和在nginx中使用lua直接访问mysql达到数据接口的统一...

    OpenResty 它打包了标准的 Nginx 核心,很多的常用的第三方模块,以及它们的大多数依赖项. 如果需要nginx的第三方库的时候,可以考虑OpenResty,可以少掉很多安装的麻烦,Open ...

  7. nginx redis mysql_Nginx + Lua + Kafka + Redis + Mysql

    写在开头 # 系统版本 cat /etc/issue CentOS release 6.8 (Final) # 切换到tmp目录 cd /tmp 安装 lua # 下载 wget http://lua ...

  8. nginx.conf添加lua.conf配置

    1.在nginx的conf下配置lua.conf......vi lua.conf server { listen 80; server_name _;location /lua { default_ ...

  9. Unity3D 基于XLua框架实现Lua组件化开发方式(一)----基于C#调用Lua

    众所周知Unity的开发语言是C#,并不支持Lua语言,为了解决这一问题出现了诸如Xlua.ULua.ToLua等框架来让unity支持lua,由于为了应对众多游戏经常需要解决的热更新问题,出了两种主 ...

  10. fastdfs+nginx+keepalived+openoffice+lua 实现文件上传、下载、水印、预览(word、excel、ppt、txt),feign文件上传

    前言 最近刚刚实现的文件服务中心,记录一下,为没做过的人提供一下思路,由于本人技术有限,不足之处欢迎批评指正,共同学习,共同进步. 目录 Fastdfs集群搭建 搭建keepalived 实现ngxi ...

最新文章

  1. postgresql 比较两个时间差大于 N个小时
  2. 进制转换(洛谷-P1017)
  3. matlab中怎么表示概率,[转载]matlab中的概率函数
  4. 海量数据处理相关算法及数据结构【转】
  5. Multisim14简介与安装
  6. 1041 例题4-2 比较交换实数值
  7. 一个如何在bash中使用getopts的例子
  8. 美团:后端开发工程师(实习生)面试
  9. Mac上常用软件-2018
  10. twitter三方登录的实现
  11. 庆祝JavaCard技术领导SmartCard技术超过五年
  12. Eloquent JavaScript 笔记 九: Regular Expressions(下)
  13. @media媒体查询——详解
  14. 已知三角形三个顶点求内切圆和外接圆半径 以及面积 C语言模板
  15. matlab 播放声音,Matlab:实时播放音频并显示波形
  16. 深圳图高智能深耕5G三防夜视智能终端细分领域,引领行业发展
  17. 三相永磁同步电机(PMSM) SVPWM矢量控制 MATLA 仿真算法
  18. 东南大学计算机学研招生人数,东南大学2020硕士研究生各专业报录比汇总(实考人数:录取人数)...
  19. 三相整流器移相触发电路的整体FPGA设计
  20. linux 帐户安全管理员权限,Linux系统账号安全控制

热门文章

  1. NoSQLBooster for MongoDB 算法注册机
  2. 互联网日报 | 4月5日 星期一 | 华为首款台式显示器登陆海外;腾讯视频VIP会员4月10日起涨价;我国民宿房源超300万套...
  3. 洛谷P4563 [JXOI2018]守卫
  4. 2021中国科技大学计算机博士招生,中国科学技术大学2021年拟录取博士研究生名单公示,2661人!...
  5. linux下gpt分区,Linux下的GPT分区
  6. 百度热力图颜色说明_揭秘!张家口100万人口热力图,看完你就知道房子该买哪里了...
  7. 关于计算机教学的论文,关于计算机教学论文.docx
  8. 迅雷下载太慢怎么办?
  9. 树莓派(4B)入门教程
  10. ssm框架搭建连接mysql_搭建SSM框架(一) - xiaoqi__y的个人空间 - OSCHINA - 中文开源技术交流社区...