Lua在Nginx中的应用

Scroll Down

Lua介绍

  1. 什么是lua?

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

  1. lua的特点?
  • 轻量级: 它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
  • 易扩展: Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
  • 嵌入式和可扩展语言:提供与 C/C++ 之间的直接接口。
  1. 应用场景?
  • 游戏开发
  • 独立应用脚本
  • Web 应用脚本
  • 扩展和数据库插件
  • 安全系统,如入侵检测系统

Lua语法

基本数据类型

类型名类型介绍示例
nil只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。a= nil
boolean包含两个值:false和true。a=true
number表示双精度类型的实浮点数(Lua没有整数类型)a= 0.765
string字符串由一对双引号或单引号来表示a= "Hello world"
table数组、容器a = {11,12,13,14}

Lua变量

Lua变量分为全局变量和局部变量

-- test.lua 文件脚本
a = 5               -- 全局变量
local b = 5         -- 局部变量

function joke()
    c = 5           -- 全局变量
    local d = 6     -- 局部变量
end

joke()
print(c,d)          --> 5 nil

do
    local a = 6     -- 局部变量
    b = 6           -- 对局部变量重新赋值
    print(a,b);     --> 6 6
end

print(a,b)      --> 5 6

条件语句

条件控制:if 条件 then 语句 else 语句 end
aa = 3
if aa>3 then
    print("aa>3")
 else
    print("aa<3")
 end

-- 输出:aa<3

while循环
while 循环:while 条件 do ... end
aa = 0
while aa <=4 do
    print("aa<4")
    aa = aa+1
end
print("aa>4")

-- 输出
--aa<4
--aa<4
--aa<4
--aa<4
--aa<4
--aa>4

for循环
for 变量= 初值,终点值,步进值 do 语句 end
--注意,5是可以取到的
for i=0,5,1 do print(i) end

-- 输出:
-- 0
-- 1
-- 2
-- 3
-- 4 
-- 5

repeat until

aa = 1
repeat         
    print(aa)   -- 打印aa 的值
    aa=aa+1     -- aa 自加一
until aa>3      -- 判断aa的值是否大于 3 ,大于则结束

-- 输出:
-- 1
-- 2
-- 3
aa = 10
repeat         
    print(aa)   -- 打印aa 的值
    aa=aa+1     -- aa 自加一
until aa>3      -- 判断aa的值是否大于 3 ,大于则结束

-- 输出:
-- 10   先进入一次,然后判断,可以用到必须执行一次的地方

函数

function 函数名()

语句

end

Lua模块调用

-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
 
-- 定义一个常量
module.constant = "这是一个常量"

local function func2()
    print("这是一个私有函数!")
end
 
function module.func3()
    func2()
end
 
return module

模块调用

require("<模块名>")

操作table

-- 初始化表
mytable = {}

-- 指定值
mytable[1]= "Lua"

-- 移除引用
mytable = nil
-- lua 垃圾回收会释放内存
-- 简单的 table
mytable = {}
print("mytable 的类型是 ",type(mytable))

mytable[1]= "Lua"
mytable["wow"] = "修改前"
print("mytable 索引为 1 的元素是 ", mytable[1])
print("mytable 索引为 wow 的元素是 ", mytable["wow"])

-- alternatetable和mytable的是指同一个 table
alternatetable = mytable

print("alternatetable 索引为 1 的元素是 ", alternatetable[1])
print("mytable 索引为 wow 的元素是 ", alternatetable["wow"])

alternatetable["wow"] = "修改后"

print("mytable 索引为 wow 的元素是 ", mytable["wow"])

-- 释放变量
alternatetable = nil
print("alternatetable 是 ", alternatetable)

-- mytable 仍然可以访问
print("mytable 索引为 wow 的元素是 ", mytable["wow"])

mytable = nil
print("mytable 是 ", mytable)

结果

mytable 的类型是     table
mytable 索引为 1 的元素是     Lua
mytable 索引为 wow 的元素是     修改前
alternatetable 索引为 1 的元素是     Lua
mytable 索引为 wow 的元素是     修改前
mytable 索引为 wow 的元素是     修改后
alternatetable 是     nil
mytable 索引为 wow 的元素是     修改后
mytable 是     nil

OpenResty 介绍

OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web 平台,由中国人章亦春发起,提供了很多高质量的第三方模块。

OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。

360,UPYUN,阿里云,新浪,腾讯网,去哪儿网,酷狗音乐等都是 OpenResty 的深度用户。

使用lua+nginx限流的简单案例

Lua

--是否开启检测
local check = "on"    
--限制最大访问量
local count = 2
--限制时间范围
local seconds = 10

--对uri 进行限制主要逻辑
function access_user_uri_check()
	if check=="on" then
		--192.168.248.100:8999 /limit
		local key = ngx.var.host..ngx.var.uri
		--提前在nginx中声明的变量
		local limit = ngx.shared.limit
		local req
		if limit then
			req = limit:get(key)
		end
		if req then
			if req>=count then
				--超过限制之后返回错误
				ngx.say("您在最近:"..seconds.."秒,访问:"..access_uri.."次数超过:"..count.."次,已经触发保护机制,请稍后访问")
				ngx.exit(403)
			end
			--对key对应的数据进行累加
			limit:incr(key,1)
			
		else
			--没有值设置初始为1
			limit:set(key,1,seconds)
		end
	end
end

nginx.conf

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
	charset utf-8;
    keepalive_timeout  65;

    lua_shared_dict limit 10m;
    server {
        listen       8999;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
	location /sayhello{
        default_type 'text/html';
        content_by_lua 'ngx.say("hello,lua")';
    }
	
	location /limit{
		default_type 'text/html';
		#嵌入的lua脚本
        access_by_lua_file "/www/nginx/lua/access_nginx_check.lua";
		content_by_lua 'ngx.say("hello,lua")';
    }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}