1 Idea中创建Lua项目

  lua官网:https://www.lua.org/

1.1 添加插件,重启idea

1.2 创建项目

  file-New Project

1.3 创建lua文件

1.4 配置lua运行程序

1)下载

  https://github.com/rjpcomputing/luaforwindows/releases

  

 2)安装

  直接按照就好

3)配置Debug

  program选择lua安装路径

1.5 测试

  代码

local function main()
print("hello world")
end main()

  执行

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.3 变量

1)数字类型

  Lua的数字只有double型,64bits

  你可以以如下的方式表示数字

num = 1024

num = 3.0

num = 3.1416

num = 314.16e-2

num = 0.31416E1

num = 0xff

num = 0x56

2)字符串

  可以用单引号,也可以用双引号

  也可以使用转义字符‘\n’ (换行), ‘\r’ (回车), ‘\t’ (横向制表), ‘\v’ (纵向制表), ‘\’ (反斜杠), ‘\”‘ (双引号), 以及 ‘\” (单引号)等等

  下面的四种方式定义了完全相同的字符串(其中的两个中括号可以用于定义有换行的字符串)

a = 'alo\n123"'

a = "alo\n123\""

a = '\97lo\10\04923"'

a = [[alo

123"]]

3)空值

  C语言中的NULL在Lua中是nil,比如你访问一个没有声明过的变量,就是nil

4)布尔类型

  只有nil和false是 false

  数字0,‘’空字符串(’\0’)都是true

5)作用域

  lua中的变量如果没有特殊说明,全是全局变量,那怕是语句块或是函数里。

  变量前加local关键字的是局部变量

2.4 控制语句

1)while循环

local i = 0

local max = 10

while i <= max do

print(i)

i = i +1

end

2)if-else

local function main()

local age = 140

local sex = 'Male'

  if age == 40 and sex =="Male" then
print(" 男人四十一枝花 ")
elseif age > 60 and sex ~="Female" then print("old man without country!")
elseif age < 20 then
io.write("too young, too naive!\n") else
print("Your age is "..age)
end end -- 调用
main()

3)for循环

sum = 0

for i = 100, 1, -2 do

    sum = sum + i

end

2.5 函数

function myPower(x,y)

  return      y+x

end

power2 = myPower(2,3)

 print(power2)
function newCounter()

   local i = 0
return function() -- anonymous function i = i + 1 return i end
end c1 = newCounter() print(c1()) --> 1 print(c1()) --> 2 print(c1())

2.6 返回值

name, age,bGay = "yiming", 37, false, "yimingl@hotmail.com"

print(name,age,bGay)
function isMyGirl(name)
return name == 'xiao6' , name
end local bol,name = isMyGirl('xiao6') print(name,bol)

2.7 Table

key,value的键值对 类似 map

lucy = {name='xiao6',age=18,height=165.5}

xiao6.age=35

print(xiao6.name,xiao6.age,xiao6.height)

print(xiao6)

2.8 数组

arr = {"string", 100, "xiao6",function() print("memeda") return 1 end}

print(arr[4]())
遍历
for k, v in pairs(arr) do print(k, v)
end

2.9 面向对象

  成员函数

person = {name='xiao6',age = 18}

  function  person.eat(food)

    print(person.name .." eating "..food)

  end
person.eat("xxoo")

3 Lua整合redis

  从redis2.6.0版本开始,通过内置的lua编译器和解析器,可以使用eval命令执行lua脚本

3.1 在redis客户端中执行简单lua脚本

  登录到客户端后执行

eval   "return 1+1"    0
#命令 脚本 参数个数

EVAL "local msg='hello world' return msg..KEYS[1]" 1 AAA BBB
#...表示拼接字符串

  表是基于1的,也就是说索引以数值1开始。所以在表中的第一个元素就是mytable[1],第二个就是mytable[2]等等。

   表中不能有nil值。如果一个操作表中有[1, nil, 3, 4],那么结果将会是[1]——表将会在第一个nil截断

3.2 执行独立脚本test.lua

1)创建一个脚本

local list=redis.call("get","qq");  

return list;

2)执行脚本

redis-cli -p 6379 -a 573875306 --eval /usr/local/programs/redis-5.0.10/mylua/test.lua 0

3)带参数

  test.lua

local num = redis.call('get',KEYS[1]);
if not num then
return num;
else
local res = num * KEYS[2] * ARGV[1];
redis.call('set',KEYS[1],res);
return res;
end;

  执行

  这里要说明一下linux中执行lua脚本参数传值和redis命令执行lua脚本传值的差异问题。

  如果传入多个参数,那么在redis命令中,需要指定key的个数,所有的key和argv参数之间都使用空格分隔即可,lua脚本执行时,会根据传入的key个数自动区分开key参数和argv参数;

  但是在linux命令中,key参数和argv参数要用逗号分隔,key和key之间、argv与argv之间用空格分隔,如果key和argv之间不使用逗号,则会抛出异常,并且逗号前后需有空格,否则会被认为是传的一个参数,同样会抛出异常

redis-cli -p 6379 -a 573875306 --eval /usr/local/programs/redis-5.0.10/mylua/test.lua launumber 20 , 30

  

3.3 Lua 与 Redis 交互

3.3.1 Lua 脚本获取 EVAL & EVALSHA 命令的参数

  通过 Lua 脚本的全局变量 KEYS 和 ARGV,能够访问 EVAL 和 EVALSHA 命令的 key [key ...] 参数和 arg [arg ...] 参数。

  作为 Lua Table,能够将 KEYS 和 ARGV 作为一维数组使用,其下标从 1 开始。

3.3.2 Lua 脚本内部执行 Redis 命令

  Lua 脚本内部允许通过内置函数执行 Redis 命令:

  redis.call()

  redis.pcall()

  两者非常相似,区别在于:

  若 Redis 命令执行错误,redis.call() 将错误抛出(即 EVAL & EVALSHA 执行出错);

  redis.pcall() 将错误内容返回。

  local msg='count:' local count = redis.call("get","count") if not count then redis.call("set","count",1) end redis.call("incr","count") return msg..count+1

3.3.3 redis WATCH/MULTI/EXEC 与Lua

  redis 原生支持 监听、事务、批处理,那么还需要lua吗?

  • 两者不存在竞争关系,而是增强关系,lua可以完成redis自身没有的功能

  • 在lua中可以使用上一步的结果,也就是可以开发后面操作依赖前面操作的执行结果的应用,MULT中的命令都是独立操作

  • redis可以编写模块增强功能,但是c语言写模块,太难了,lua简单的多

  • 计算向移动数据

  • 原子操作

  lua脚本尽量短小并且尽量保证同一事物写在一段脚本内,因为redis是单线程的,过长的执行会造成阻塞,影响服务器性能。

3.3.4 Redis Lua 脚本管理

  1)script load 此命令用于将Lua脚本加载到Redis内存中

  2)script exists scripts exists sha1 [sha1 …] 此命令用于判断sha1是否已经加载到Redis内存中

  3)script flush 此命令用于清除Redis内存已经加载的所有Lua脚本,在执行script flush后,sha1不复存在

  4)script kill 此命令用于杀掉正在执行的Lua脚本

3.3.5 死锁

  下面代码会进入死循环,导致redis无法接受其他命令。

eval "while true do end" 0
127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.

  但是可以接受 SCRIPT KILL or SHUTDOWN NOSAVE. 两个命令

  SHUTDOWN NOSAVE 不会进行持久化的操作

  SCRIPT KILL 可以杀死正在执行的进程

3.4 生产环境下部署

  加载到redis

redis-cli script load "$(cat test.lua)"

  得到sha1值

  执行

redis-cli evalsha "7a2054836e94e19da22c13f160bd987fbc9ef146" 0

4 openresty安装使用(lua整合nginx)

  我们都知道Nginx有很多的特性和好处,但是在Nginx上开发成了一个难题,Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏。为了开发人员方便,所以接下来我们要介绍一种整合了Nginx和lua的框架,那就是OpenResty,它帮我们实现了可以用lua的规范开发,实现各种业务,并且帮我们弄清楚各个模块的编译顺序。关于OpenResty,我想大家应该不再陌生,随着系统架构的不断升级、优化,OpenResty在被广泛的应用

4.1 下载

  http://openresty.org/cn/download.html

4.2 安装

  官方文档安装介绍:http://openresty.org/cn/installation.html

1)下载好的文件

2)上传到服务器解压 

  tar -xzvf xxx

3)进入目录/usr/local/openresty-1.21.4.1

4)环境准备  

  yum install pcre-devel openssl-devel gcc curl -y

5)安装perl

  https://www.cnblogs.com/jthr/p/16911499.html

6)执行

  ./configure

7) 安装

  程序会被安装到`/usr/local/openresty`目录

make

make install

8) 启动

./nginx -c /usr/local/openresty/nginx//conf/nginx.conf

9)访问

4.3 相关命令

4.3.1 服务命令

1)启动

Service openresty start

2)停止

Service openresty stop

3)检查配置文件是否正确

Nginx -t

4)重新加载配置文件

Service openresty reload

5)查看已安装模块和版本号

Nginx -V

5 nginx使用lua扩展

5.1 简单使用

1)进入目录

  这里进入的是openresty下的nginx目录,这就是一个全新的可以使用lua扩展的nginx

2)修改配置文件nginx.conf

  /usr/local/openresty/nginx/conf

  首先修改下端口号,免得冲突:server下的 listen属性

listen       8099;

  在server下添加一个local

  location /lua {
default_type text/html;
content_by_lua_file /usr/local/openresty/nginx/lua/hello.lua; #也可以用相对路径,相对目录在nginx下
}

3)进入上面配置的目录,创建hello.lua

  添加内容

ngx.say("<p>Hello, World!</p>")

4)重新启动

./nginx -s stop
./nginx -c /usr/local/openresty/nginx//conf/nginx.conf

5)访问

http://192.168.28.110:8099/lua

  如果出错,可以在/usr/local/openresty/nginx/logs下查看日志查找原因

5.2 配置热部署

  没有配置热部署,修改hello.lua,都需要重新启动

  修改配置文件:/usr/local/openresty/nginx/conf/nginx.conf

  在http下加上配置:lua_code_cache off; #热部署,每次执行都编译

  

  重新启动,再修改hello.lua直接刷新页面就可以

5.3 其它示例

1)获取Nginx请求头信息

local headers = ngx.req.get_headers()                         

ngx.say("Host : ", headers["Host"], "<br/>")  

ngx.say("user-agent : ", headers["user-agent"], "<br/>")  

ngx.say("user-agent : ", headers.user_agent, "<br/>")

for k,v in pairs(headers) do  

    if type(v) == "table" then  

        ngx.say(k, " : ", table.concat(v, ","), "<br/>")  

    else  

        ngx.say(k, " : ", v, "<br/>")  

    end  

end  

2)获取post请求参数

ngx.req.read_body()  

ngx.say("post args begin", "<br/>")  

local post_args = ngx.req.get_post_args()  

for k, v in pairs(post_args) do  

    if type(v) == "table" then  

        ngx.say(k, " : ", table.concat(v, ", "), "<br/>")  

    else  

        ngx.say(k, ": ", v, "<br/>")  

    end
end

3)获取http协议版本

ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "<br/>")

4)获取请求方法

ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "<br/>")

5)获取原始的请求头内容  

ngx.say("ngx.req.raw_header : ",  ngx.req.raw_header(), "<br/>")  

6)获取body内容体  

ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "<br/>")

6 Nginx全局内存缓存

  多进程共享,且能保障原子性。可以通过lua去访问它。

  重载Nginx配置时,缓存数据会丢失。

1)修改配置文件:/usr/local/openresty/nginx/conf/nginx.conf

 在http下加上一行配置

lua_shared_dict shared_data 1m;

  重新启动

2)修改hello.lua

local shared_data = ngx.shared.shared_data  

local i = shared_data:get("i")  

if not i then  

    i = 1  

    shared_data:set("i", i)  

    ngx.say("lazy set i ", i, "<br/>")
end i = shared_data:incr("i", 1) ngx.say("i=", i, "<br/>")

3)访问

7 lua-resty-lrucache缓存

  gihub地址:https://github.com/openresty/lua-resty-lrucache

  Lua 实现的一个简单的 LRU 缓存,适合在 Lua 空间里直接缓存较为复杂的 Lua 数据结构

  它相比 ngx_lua 共享内存字典可以省去较昂贵的序列化操作,相比 memcached 这样的外部服务又能省去较昂贵的 socket 操作

  1)支持更丰富的数据类型,可以把table存放在value中,这对数据结构复杂的业务非常有用。

  2)可以预先分配key的数量,不用设置固定的内存空间,在内存的使用上更为灵活。

  3)每个worker进程独立缓存,所以当worker进程同时读取同一个key 时不存在锁竞争。

  但它与lua_shared_dict相比也有一些缺点

  1)因为数据不在worker之间共享,所以无法保证在更新数据时,数据在同一时间的不同worker进程上完全一致。

  2)虽然可以支持复杂的数据结构,但可使用的指令却很少,如不支持消息队列功能。

  3)重载Nginx配置时,缓存数据会丢失。如果使用lua_shared_dict,则不会如此

1)修改配置文件:/usr/local/openresty/nginx/conf/nginx.conf

  注释掉热部署,每次都编译对缓存会造成影响,使用不正确

#lua_code_cache off; #热部署,每次执行都编译

  之前配置的location 进行修改

location /lua {
default_type text/html;
content_by_lua_block {
require("my/cache").go()
}
}

2)编码

  在/usr/local/openresty/lualib创建文件夹my(因为上面配置的相对路径,它会在这些目录下去找)

  

  在my下创建文件cache.lua

  

  写入内容

local _M = {}

lrucache = require "resty.lrucache"

c, err = lrucache.new(200)  -- allow up to 200 items in the cache
ngx.say("count=init") if not c then
error("failed to create the cache: " .. (err or "unknown"))
end function _M.go() count = c:get("count") c:set("count",100)
ngx.say("count=", count, " --<br/>") if not count then c:set("count",1) ngx.say("lazy set count ", c:get("count"), "<br/>") else c:set("count",count+1) ngx.say("count=", count, "<br/>")
end end
return _M

3)重启

4)访问

8 openresty连接redis(lua-resty-redis)

  https://www.cnblogs.com/jthr/p/16934706.html

Nginx10 Lua入门 + openresty的更多相关文章

  1. Openresty最佳案例 | 第2篇:Lua入门

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616622 本文出自方志朋的博客 什么是lua Lua 是一种轻量小巧的脚本语言,用标准 ...

  2. lua入门demo(HelloWorld+redis读取)

    1. lua入门demo 1.1. 入门之Hello World!! 由于我习惯用docker安装各种软件,这次的lua脚本也是运行在docker容器上 openresty是nginx+lua的各种模 ...

  3. Lua入门记录

    学习资料 Lua入门和Lua高阶章节 Lua中文文档 阅读笔记,只是记录了知识点和一些注意点,详细的看上面提供的学习资料链接 Lua 基础数据类型 nil(空) boolean(布尔) Lua 中 n ...

  4. 畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 畅购商城(一):环境搭建 畅购商 ...

  5. OpenResty(nginx+lua) 入门

    OpenResty 官网:http://openresty.org/ OpenResty 是一个nginx和它的各种三方模块的一个打包而成的软件平台.最重要的一点是它将lua/luajit打包了进来, ...

  6. 安装lua和openresty

    #### ubuntu 16.04 64bit 安装Lua luajit 及openresty 1 安装lua ,因为luajit 支持lua5.1较好.貌似不支持5.2和5.3作为学习,我就安装5. ...

  7. [置顶] 轻量级语言Lua入门

    作为一个脚本爱好者,而且是脚本(Perl)起家的我,一有空就喜欢学习下这些脚本语言.据说魔兽世界.愤怒小鸟都用到了它,所以今天研究下Lua这个叫法有点奇特的脚本 [转载请注明出处:http://blo ...

  8. lua 入门学习

    -- 1.Hello world print( "--------------1--------------") print("Hello world"); - ...

  9. [Lua]入门教程

    什么是Lua Lua 是一个小巧的脚本语言.是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Rober ...

  10. lua入门

    print("hello lua") lua官网 在线运行代码 数据类型 数据类型 描述 number 数字,可当作double,5/2 == 2.5 string 字符串 nil ...

随机推荐

  1. 云原生之旅 - 11)基于 Kubernetes 动态伸缩 Jenkins Build Agents

    前言 上一篇文章 云原生之旅 - 10)手把手教你安装 Jenkins on Kubernetes 我们介绍了在 Kubernetes 上安装 Jenkins,本文介绍下如何设置k8s pod作为Je ...

  2. 不一样的纯H5C3动画爱心

    最近抖音很火的让你会计算机的朋友给你做个爱心突然火了,我也不出意外的收到了朋友的邀请,自己做肯定太麻烦了于是乎百度第一步,惊呆了!网上全都是一个爱心,变着法的火焰爱心,换汤不换药,那我们肯定是要整点不 ...

  3. Vue2学习笔记

    1.插值语法: 1.1.功能: 用于解析标签体内容 1.2.写法: {{ xxx }},xxx是js表达式,且可以直接读取到data中的所有属性. 2.收集表单数据 若:<input type= ...

  4. 大前端html基础学习01

    根目录 相对路径:针对图片数量比较多的情况,新建一个文件夹,将所有图片放进去,imgs/cat.webp (1)/:下一级 (2)a/b/c/cat.webp 返回路径(向外找):从下一级html中找 ...

  5. 【Devexpress】Gridcontrol列标题换行

    gridView1.OptionsView.AllowHtmlDrawHeaders = true; gridView1.ColumnPanelRowHeight = 35; GridColumn g ...

  6. 我要涨知识——TypeScript 常见面试题(二)

    又是一个年底来了,好大一批人可能又准备跑路了,最近回家待产,翻了翻掘金和 CSDN 发现好多大佬都有大厂 Offer ,看着看着我心动了! 话不多说,赶紧开干,给自己整了一个前端面试小助手--微信小程 ...

  7. ArcObjects SDK开发 003 宏观角度看ArcObjects SDK

    1.为什么要宏观上看ArcObjects SDK ArcObjects SDK库是一个非常庞大复杂COM组件集合,ArcGIS10.0有1000多个枚举.90多个结构体.5000多个接口以及4000多 ...

  8. 浅聊一下Django如何避免xss攻击

    一.什么是xss攻击 xss攻击:----->web注入 xss跨站脚本攻击(Cross site script,简称xss)是一种"HTML注入",由于攻击的脚本多数时候是 ...

  9. MYSQL进阶学习笔记

    MySQL在Linux中的使用: 1.查看mysql在linux的安装版本 mysqladmin –version 2.mysql服务的启动与停止 (1).启动: service mysql star ...

  10. 把ChatGPT配置到微信群里,可以对AI提问了!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言:用的很爽! 自从小傅哥用上 ChatGPT 连搜索引擎用的都不多了,很多问题的检索我 ...