目錄
一、前言
二、Lua基礎(chǔ)語法??
hello world
保留關(guān)鍵字
注釋
變量
字符串
空值
布爾類型
作用域
控制語句
if-else
for循環(huán)
函數(shù)
賦值
返回值?
Table
數(shù)組
遍歷
成員函數(shù)
三、openresty的安裝
(一)預(yù)編譯安裝
(二)源碼編譯安裝
(三)服務(wù)命令
(四)測試lua腳本以文件的形式
代碼熱部署
獲取nginx請求頭信息
獲取post請求參數(shù)
Http協(xié)議版本
請求方法
原始的請求頭內(nèi)容
body內(nèi)容體
(五)Nginx緩存
Nginx全局內(nèi)存緩存
lua-resty-lrucache
lua-resty-redis訪問redis
lua-resty-mysql
一、前言
Lua 是由巴西里約熱內(nèi)盧天主教大學(xué)(Pontifical Catholic University of Rio de Janeiro)里的一個研究小組于1993年開發(fā)的一種輕量、小巧的腳本語言,用標(biāo)準(zhǔn) C 語言編寫,其設(shè)計目的是為了嵌入應(yīng)用程序中,從而為應(yīng)用程序提供靈活的擴(kuò)展和定制功能。
官網(wǎng):The Programming Language Lua
學(xué)習(xí)lua語言之前需要先安裝lua版本,并在ideal下載插件,具體的可以看下面這篇文章
Lua環(huán)境安裝+Idea配置_idea配置lua_xiaowu714的博客-CSDN博客https://blog.csdn.net/xiaowu714/article/details/127763087?spm=1001.2014.3001.5506
二、Lua基礎(chǔ)語法??
hello world
在ideal新建lua項目并創(chuàng)建lua文件后輸入以下內(nèi)容
local function main()
print("Hello world!")
end
main()
運(yùn)行結(jié)果
保留關(guān)鍵字
and break do else elseif end false for function
if in local nil not or repeat return then true
until while
注釋
-- 兩個減號是行注釋
--[[
這是塊注釋
這是塊注釋.
--]]
變量
數(shù)字類型
Lua的數(shù)字只有double型,64bits
你可以以如下的方式表示數(shù)字
num = 1024?
num = 3.0?
num = 3.1416
?num = 314.16e-2
?num = 0.31416E1
?num = 0xff?
num = 0x56
字符串
可以用單引號,也可以用雙引號
也可以使用轉(zhuǎn)義字符‘\n’ (換行), ‘\r’ (回車), ‘\t’ (橫向制表), ‘\v’ (縱向制表), ‘\’ (反斜杠), ‘\”‘ (雙引號), 以及 ‘\” (單引號)等等
下面的四種方式定義了完全相同的字符串(其中的兩個中括號可以用于定義有換行的字符串)
a = 'alo\n123"'
a = "alo\n123\""
a = '\97lo\10\04923"'
a = [[alo
123"]]
空值
C語言中的NULL在Lua中是nil,比如你訪問一個沒有聲明過的變量,就是nil
布爾類型
只有nil和false是 false
數(shù)字0,‘’空字符串(’\0’)都是true
作用域
lua中的變量如果沒有特殊說明,全是全局變量,那怕是語句塊或是函數(shù)里。
變量前加local關(guān)鍵字的是局部變量。
控制語句
while循環(huán)
local function main()
local i = 0
local max = 10
while i <= max do
print(i)
i = i + 1
end
end
main()
運(yùn)行結(jié)果
if-else
local function main()
local age = 30
local sex = 'Malee'
if age <= 40 and sex == "Male" then
print("男人四十一枝花")
elseif age > 40 and sex ~= "Female" then -- ~= 等于 !=
io.write("old man")
elseif age < 20 then
print("too young too simple")
else
print("Your age is "..age) --Lua中字符串的連接用..
end
end
main()
for循環(huán)
local function main()
for i = 10, 1 , -1 do -- i<=1, i--
print(i)
end
for i = 1, 10 , 1 do -- i<=10, i++
print(i)
end
end
main()
函數(shù)
local function main()
function myPower(x,y) -- 定義函數(shù)
return y+x
end
power2 = myPower(2,3) -- 調(diào)用
print(power2)
end
main()
local function main()
function newCounter()
local i = 0
return function() -- anonymous function(匿名函數(shù))
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) --> 1
print(c1()) --> 2
print(c1())
end
main()
賦值
local function main()
name, age,bGay = "yiming", 37, false, "yimingl@hotmail.com" -- 多出來的舍棄
print(name,age,bGay)
end
main()
返回值?
local function main()
function isMyGirl(name)
return name == 'xiao6' , name
end
local bol,name = isMyGirl('xiao6')
print(name,bol)
end
main()
?
Table
KV形式,類似map
local function main()
dog = {name='111',age=18,height=165.5}
dog.age=35
print(dog.name,dog.age,dog.height)
print(dog)
end
main()
數(shù)組
local function main()
local function main()
arr = {"string", 100, "dog",function() print("wangwang!") return 1 end}
print(arr[4]())
end
main()
end
main()
遍歷
local function main()
arr = {"string", 100, "dog",function() print("wangwang!") return 1 end}
for k, v in pairs(arr) do
print(k, v)
end
end
main()
成員函數(shù)
local function main()
person = {name='旺財',age = 18}
function person.eat(food)
print(person.name .." eating "..food)
end
person.eat("骨頭")
end
main()
三、openresty的安裝
(一)預(yù)編譯安裝
以CentOS舉例 其他系統(tǒng)參照:OpenResty - OpenResty? Linux 包
你可以在你的 CentOS 系統(tǒng)中添加 openresty 倉庫,這樣就可以便于未來安裝或更新我們的軟件包(通過 yum update 命令)。運(yùn)行下面的命令就可以添加我們的倉庫:
? yum install yum-utils
? yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
然后就可以像下面這樣安裝軟件包,比如 openresty:
? yum install openresty
如果你想安裝命令行工具 resty,那么可以像下面這樣安裝 openresty-resty 包:
? sudo yum install openresty-resty
(二)源碼編譯安裝
官網(wǎng)下載tar.gz包
OpenResty - 下載
最小版本基于nginx1.21
./configure
然后在進(jìn)入 openresty-VERSION/
目錄, 然后輸入以下命令配置:
./configure
默認(rèn), --prefix=/usr/local/openresty
程序會被安裝到/usr/local/openresty
目錄。
依賴 gcc openssl-devel pcre-devel zlib-devel
安裝:yum install gcc openssl-devel pcre-devel zlib-devel postgresql-devel
您可以指定各種選項,比如
./configure --prefix=/opt/openresty \
--with-luajit \
--without-http_redis2_module \
--with-http_iconv_module \
--with-http_postgres_module
試著使用 ./configure --help
查看更多的選項。
make && make install
查看openresty的目錄
(三)服務(wù)命令
啟動
Service openresty start
停止
Service openresty stop
檢查配置文件是否正確
Nginx -t
重新加載配置文件
Service openresty reload
查看已安裝模塊和版本號
Nginx -V
測試Lua腳本
在Nginx.conf 中寫入
location /lua {
default_type text/html;
content_by_lua '
ngx.say("<p>Hello, World!</p>")
';
}
啟動nginx
./nginx -c /usr/local/openresty/nginx/conf/nginx.conf
(四)測試lua腳本以文件的形式
location /lua {
default_type text/html;
content_by_lua_file lua/hello.lua;
}
?在nginx目錄下創(chuàng)建lua目錄并寫入hello.lua文件,文件內(nèi)容
ngx.say("<p>hello world!!!</p>")
代碼熱部署
hello.lua腳本每次修改都需要重啟nginx,很繁瑣,因此可以通過配置開啟熱部署
?lua_code_cache off;
?會提示開啟該功能可能影響nginx的性能
獲取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
?
獲取post請求參數(shù)
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
?
Http協(xié)議版本
ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "<br/>")
請求方法
ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "<br/>")
原始的請求頭內(nèi)容
ngx.say("ngx.req.raw_header : ", ngx.req.raw_header(), "<br/>")
body內(nèi)容體
ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "<br/>")
(五)Nginx緩存
Nginx全局內(nèi)存緩存
nginx配置文件的http塊中添加
lua_shared_dict shared_data 1m; # 申請一兆內(nèi)存作為內(nèi)存緩存,該內(nèi)存可以被所有的進(jìn)程進(jìn)行共享的且可以保持原子性
hello.lua腳本內(nèi)容
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/>")
接下來每次都會從訪問ii都會+1
lua-resty-lrucache
Lua 實現(xiàn)的一個簡單的 LRU 緩存,適合在 Lua 空間里直接緩存較為復(fù)雜的 Lua 數(shù)據(jù)結(jié)構(gòu):它相比 ngx_lua 共享內(nèi)存字典可以省去較昂貴的序列化操作,相比 memcached 這樣的外部服務(wù)又能省去較昂貴的 socket 操作
https://github.com/openresty/lua-resty-lrucache
引用lua文件
location /lua {
default_type text/html;
# content_by_lua_file lua/hello.lua;
content_by_lua_block {
require("my/cache").go()
}
}
當(dāng)不知道nginx是在哪個文件下查找時可以先重啟nginx,然后訪問報錯試一下,然后在error.log文件中可以看到默認(rèn)在哪些文件下查找
我們在lualib下創(chuàng)建my目錄,并在my目錄下創(chuàng)建cache.lua腳本,腳本內(nèi)容如下:
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
記得開啟lua_code_cache,即代碼緩存,不然每次代碼都會重復(fù)執(zhí)行,永遠(yuǎn)都拿不到count的值
lua-resty-redis訪問redis
官網(wǎng):GitHub - openresty/lua-resty-redis: Lua redis client driver for the ngx_lua based on the cosocket API
常用方法
local res, err = red:get("key")
local res, err = red:lrange("nokey", 0, 1)
ngx.say("res:",cjson.encode(res))
創(chuàng)建連接
red, err = redis:new()
ok, err = red:connect(host, port, options_table?)
timeout
red:set_timeout(time)
keepalive
red:set_keepalive(max_idle_timeout, pool_size)
close
ok, err = red:close()
pipeline
red:init_pipeline()
results, err = red:commit_pipeline()
認(rèn)證
local res, err = red:auth("foobared")
if not res then
ngx.say("failed to authenticate: ", err)
return
end
nginx的配置
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
lua_code_cache off;
lua_shared_dict shared_data 1m;
server {
listen 888;
server_name localhost;
location /lua {
default_type text/html;
content_by_lua_file lua/redis.lua;
}
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
redis.lua腳本
local redis = require "resty.redis"
local red = redis:new()
red:set_timeouts(1000, 1000, 1000) -- 1 sec
local ok, err = red:connect("127.0.0.1", 6379)
local res, err = red:auth("zjy123...000")
if not res then
ngx.say("failed to authenticate: ", err)
return
end
if not ok then
ngx.say("failed to connect: ", err)
return
end
ok, err = red:set("dog", "an animal")
if not ok then
ngx.say("failed to set dog: ", err)
return
end
ngx.say("set result: ", ok)
local res, err = red:get("dog")
if not res then
ngx.say("failed to get dog: ", err)
return
end
if res == ngx.null then
ngx.say("dog not found.")
return
end
ngx.say("dog: ", res)
訪問結(jié)果
?驗證
總結(jié):
lua-resty-redis直接訪問redis可以節(jié)省原本的一些步驟,比如:
客戶端請求--nginx--tomcat--redis--tomcat--nginx--客戶端
優(yōu)化為:
客戶端請求--nginx--redis--nginx--客戶端
對于一些不常更新的放在redis的資源可以使用該方式,節(jié)省了不必要的步驟
lua-resty-mysql
官網(wǎng): GitHub - openresty/lua-resty-mysql: Nonblocking Lua MySQL driver library for ngx_lua or OpenResty
配置文件
charset utf-8;
lua_code_cache off;
lua_shared_dict shared_data 1m;
server {
listen 888;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /lua {
default_type text/html;
content_by_lua_file lua/mysql.lua;
}
}
?mysql.lua文章來源:http://www.zghlxwxcb.cn/news/detail-445189.html
local mysql = require "resty.mysql"
local db, err = mysql:new()
if not db then
ngx.say("failed to instantiate mysql: ", err)
return
end
db:set_timeout(1000) -- 1 sec
local ok, err, errcode, sqlstate = db:connect{
host = "192.168.102.100",
port = 3306,
database = "atguigudb1",
user = "root",
password = "123456",
charset = "utf8",
max_packet_size = 1024 * 1024,
}
ngx.say("connected to mysql.<br>")
local res, err, errcode, sqlstate = db:query("drop table if exists cats")
if not res then
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
return
end
res, err, errcode, sqlstate =
db:query("create table cats "
.. "(id serial primary key, "
.. "name varchar(5))")
if not res then
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
return
end
ngx.say("table cats created.")
res, err, errcode, sqlstate =
db:query("select * from student")
if not res then
ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
return
end
local cjson = require "cjson"
ngx.say("result: ", cjson.encode(res))
local ok, err = db:set_keepalive(10000, 100)
if not ok then
ngx.say("failed to set keepalive: ", err)
return
end
文章來源地址http://www.zghlxwxcb.cn/news/detail-445189.html
到了這里,關(guān)于【Nginx高級篇】Lua基礎(chǔ)語法和OpenResty的安裝的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!