76
OpenResty/Lua级编程技巧 术部 - kim

OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

  • Upload
    ho-kim

  • View
    306

  • Download
    3

Embed Size (px)

Citation preview

Page 1: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

OpenResty/Lua高级编程技巧技术部 - kim

Page 2: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Debug

Page 3: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

逻辑运算符 and、or 和 not 是经常隐藏 bug 的地方,比如:

if (type(t) == 'table' and t.x == 'abc')

就算 t 不是 table 类型,那么 lua 的短路求值也不会对 t

进行求值,所以不会引发运行时错误

Page 4: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

用 xpcall debug

function errorFunc()

local a = 20

print(a[10])

end

function errorHandle()

print(debug.traceback())

end

if xpcall(errorFunc,errorHandle) then

print("This is OK.")

else

print("This is error.")

end

Page 5: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

ngx.now() :获取当前时间,包括毫秒数

Page 6: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

os.clock() :返回CPU时间的描述,通常用于计算一段代码的执行效率

Page 7: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

os.data 日期对象函数:

print(os.date("%Y-%m-%d")) --输出2012-04-05

Page 8: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

简单的写log函数(排重)

local logsUniquify = {} ——是的,这是个全局数组

function log(message, level)

if ngx and type(ngx.log) == 'function' then

local level = level or ngx.EMERG

if not logsUniquify[level .. message] then

ngx.log(level, message)

logsUniquify[level .. message] = true

end

end

return nil

end

Page 9: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

以下的debug方式我们一般不用

1)直接抛出错误:error(“抛出个error!”)

2)assert(io.read("*number"), "invalid input")

3)Lua提供了错误处理函数pcall: r, msg = pcall(foo)

4)还可以用 xpcall

一般情况下我们是直接面对 error log 来开发 tailf

/home/openresty/nginx/logs/error.log

Page 10: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Safety

Page 11: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

URL参数转义

urlencode : ngx.escape_uri

urldecode : ngx.unescape_uri

local act = ngx.var.arg_act and

ngx.unescape_uri(ngx.var.arg_act) or ngx.var.act

Page 12: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

过滤/指定 remote_addr

ngx.var.remote_addr == "132.5.72.3"

Page 13: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

获取用户ip

ClienIP = ngx.req.get_headers()["X-Real-IP"]

if ClientIP == nil then

ClientIP = ngx.req.get_headers()["x_forworded_for"]

end

if ClientIP == nil then

ClientIP = ngx.var.remote_addr

end

Page 14: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Sql Injection

local name = ngx.unescape_uri(ngx.var.arg_name)

local quoted_name = ngx.quote_sql_str(name)

local sql = "select * from users where name = " ..

quoted_name

Page 15: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

htmlspecialchars的实现

function htmlspecialchars(str)

local rs = str or nil

if rs and type(rs) == 'string' then

rs = string.gsub(rs, '&', '&')

rs = string.gsub(rs, '"', '"')

rs = string.gsub(rs, "'", ''')

rs = string.gsub(rs, '<', '&lt;')

rs = string.gsub(rs, '>', '&gt;')

end

return rs

end

Page 16: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

htmlentities 实现

Page 17: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

过滤特殊字符

local illegal = {

["-"] = true, ["_"] = false, ["."] = false, ["!"] = true, [":"] = true, ["@"] = true,

["&"] = true, ["~"] = true, ["*"] = true, ["'"] = true, ['"'] = true, ["="] = false,

["("] = true, [")"] = true, ["["] = true, ["]"] = true, ["{"] = true, ["}"] = true,

["+"] = true, ["$"] = false, [","] = false, [";"] = true, ["?"] = true, ["%"] = true,

["^"] = true, ["/"] = true, ["|"] = true, ["#"] = true, ['-'] = true, ["_"] = false, ["。"] = true,

['!'] = true, [':'] = true, ['@'] = true, ['&'] = true, ['~'] = true, ['*'] = true, ['‘'] = true,

['’'] = true, ['“'] = true, ['”'] = true, ['('] = true, [')'] = true, ['['] = true, [']'] = true,

['{'] = true, ['}'] = true, ['+'] = true, ['¥'] = true, [','] = true, [';'] = true, ['?'] = true,

['%'] = true, ['^'] = true, ['/'] = true, ['……'] = true,

}

local filter = function(c)

if illegal[c] then

return ' '

end

return c

end

cnt = string.gsub(cnt, '([^a-zA-Z0-9])', filter)

Page 18: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Magics Convert

function escapeMagic(s)

local rs

if type(s) == 'string' then

rs = (s:gsub(‘[%-%.%+%[%]%(%)%$%^%%%?%*]',

'%%%1'):gsub('%z', '%%z'))

end

return rs

end

Page 19: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

过滤 v 中的疑似网址特征

local spos = find(v, 'www') or find(v, '%.')

or find(v, '。') or find(v, '点')

local substring = ''

if spos then

substring = string.sub(s, spos, epos)

substring = g.escapeMagic(substring)

v = string.gsub(s, substring, '')

end

Page 20: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Build Queries

bind['so_refer_key'] = g.trim(vinfo['so_refer_key'])

bind['request_from'] = 'info_relate'

bind['wt'] = 'json'

bind['qt'] = 'standard'

bind['56_version'] = ngx.var.arg_rvc

bind['so_refer_key'] = ngx.var.arg_so_refer_key or ''

local param = neturl.buildQuery(bind)

local host = 'related_video.solr.56.com' --

local port = '49715'

local uri = '/solrRelateVideo/select?' .. param

if ngx.var.arg_dg == 'ml' then

print(uri)

end

Page 21: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

xssfilter

— Filter the XSS attack

local xssfilter = require("lib.xssfilter")

local xss_filter = xssfilter.new()

data['title'] = g.htmlentities(xss_filter:filter(data['title']))

Page 22: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Sandbox

—使用 closure 创建 sandbox (安全运行环境),比如为 io.open 提供权限控制的功能:

do

local oldOpen = io.open

local checkAccess = function (file, mode)

-- check if current user with 'mode' can access the 'file'

end

io.open = function (file, mode)

if checkAccess(file, mode) then

return oldOpen(file, mode)

else

return nil, "access, denied"

end

end

end

Page 23: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Table

Page 24: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Metatable

t = {}

print(getmetatable(t))

-- 输出为 nil,table 创建时默认没有元表

--任何 table 都可以作为任何值的元表,在Lua代码中,只能设置table的元表

Page 25: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Table Sorting

t = {5,1,3,6,3,2}

t2 = table.sort(t, function(a1, a2)

return (a1 > a2) end) for i, v in pairs(t) do print(v)

end

Page 26: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

unpack(1)

— 该函数将接收数组作为参数,并从下标1开始返回该数组的所有元素:

string.find(unpack{"hello","ll"}) --等同于string.find("hello","ll")

Page 27: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

unpack(2)

— 经典应用 redis 的 hmget :

local tmpVids = {}

for i,v in ipairs(res) do

table.insert(tmpVids, tostring(v['video_id']))

end

local vextinfos = {}

local tbTimes = rds:hmget(rhkey, unpack(tmpVids))

Page 28: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

unpack(3)

— redis 添加多个有序集元素的泛型调用:

rds:zadd(rzkey, unpack(zsetData))

Page 29: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Table Size(real)

function length(tbl)

local count = 0

if type(tbl) == 'table' then

for _ in pairs(tbl) do count = count + 1 end

end

return count

end

Page 30: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Table Flip

function array_flip(tbl)

local rs = tbl

if type(tbl) == 'table' then

rs = {}

for k,v in pairs(tbl) do

rs[v] = k

end

end

return rs

end

Page 31: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Random Pick

function array_rand(tbl, m)

local rs

if type(tbl) == 'table' and next(tbl) ~= nil then

rs = {}

local order = {}

local n = #tbl

for i = 1, n do

order[i] = {rnd = math.random(), idx = i}

end

table.sort(order, function(a,b) return a.rnd < b.rnd end)

for i = 1, m do

if order[i] then rs[i] = order[i].idx end

end

end

return rs

end

Page 32: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Intersect by Key

function array_intersect_key(t1, t2)

local rs = t1

if type(t1) == 'table' and type(t2) == 'table' then

rs = {}

for k,v in pairs(t1) do

if t2[k] ~= nil then rs[k] = v end

end

end

return rs

end

Page 33: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Deep Compare

function deepcompare(t1, t2)

local ty1 = type(t1)

local ty2 = type(t2)

if ty1 ~= ty2 then return false end

-- non-table types can be directly compared

if ty1 ~= 'table' and ty2 ~= 'table' then return t1 == t2 end

-- as well as tables which have the metamethod __eq

for k1,v1 in pairs(t1) do

local v2 = t2[k1]

if v2 == nil or not deepcompare(v1,v2) then return false end

end

for k2,v2 in pairs(t2) do

local v1 = t1[k2]

if v1 == nil or not deepcompare(v1,v2) then return false end

end

return true

end

Page 34: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

模块初始化与 __index

—定义模块实例化的方法:

--[[ init module ]]

module(...)

_VERSION = '1.0.0'

--[[ indexed by current module env. ]]

local mt = {__index = _M};

--[[

instantiation

@return table

]]

function new(self)

return setmetatable({}, mt);

end

Page 35: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Default Value

function setDefault(table, default)

local mt = {__index = function() return default end }

setmetatable(table,mt)

end

tab = {x = 10, y = 20}

setDefault(tab,0)

print(tab.x,tab.z) --10 0

Page 36: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Write Prohibited

setmetatable(_M, {

__newindex = function (table, key, val)

ngx.log(ngx.EMERG, 'attempt to write to undeclared variable "' ..

key .. '" in ' .. table._NAME);

end

})

_M.unexists = "hello" -- 报错:’attempt to write to undeclared variable

"unexists" in $module'

Page 37: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Table Traversal

for k,v in g.pairsByKeys(idDel) do

print(k .. ':' .. v .. "\n")

end

function pairsByKeys(tb, f)

local a = {}

for n in pairs(tb) do table.insert(a, n) end

table.sort(a, f)

local i = 0 -- iterator variable

local iter = function() -- iterator function

i = i + 1

if a[i] == nil then return nil

else return a[i], tb[a[i]]

end

end

return iter

end

Page 38: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Sort by Value

function sortAssoc(tb, order, limit)

local rs = nil

if type(tb) == 'table' then

rs = {}

local tmp = {}

for k,v in pairs(tb) do

table.insert(tmp, {key = k, val = tonumber(v)})

end

if next(tmp) ~= nil then

if order and order == 'DESC' then

table.sort(tmp, function(a, b) return b.val < a.val end)

else

table.sort(tmp, function(a, b) return b.val > a.val end)

end

end

for i,v in ipairs(tmp) do

table.insert(rs, {v['key'], v['val']})

if limit and (i >= limit) then break end

end

end

return rs

end

Page 39: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Multi-Array Sorting

local data = {

{id=3, data=421}, {id=23, data=321}, {id=3, data=422}, {id=5, data=321},

{id=1, data=4214}, {id=3, data=44}

}

table.sort(data, function(a, b)

if a['id'] < b['id'] then

return true

elseif a['id'] == b['id'] then

if a['data'] < b['data'] then

return true

else

return false

end

else

return false

end

end)

Page 40: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Metatable Prohibited

mt = {}

mt.__metatable = "can not read/write"

setmetatable(s1, mt)

print(getmetatable(s1)) -- "cannot read/write"

setmetatable(s1, {}) -- cannot change protected metatable

Page 41: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Metamethod

Lua中提供的元表是用于帮助 Lua 数据变量完成某些非预定义功能的个性化行为,如两个table的相加。

假设a和b都是table,通过元表可以定义如何计算表达式a+b。

当Lua试图将两个table相加时,它会先检查两者之一是否有元表,然后检查该元表中是否存在__add字段,如果有,就调用该字段对应的值。

这个值就是所谓的“元方法”,这个函数用于计算table的和。

Page 42: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Function

Page 43: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Essence

Lua 将所有独立的程序块视为一个匿名函数的函数体,并且该匿名函数还具有可变长实参

Page 44: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Returning Values

1. 模块、函数可以考虑 “有效值|nil,错误信息” 这样的双值返回,resty 中的大部分模块都是这样写的

2. function 尽量返回单值,特别是业务逻辑的函数,多值返回虽然是 lua 的特色,但是不利于移植

3. 空值或者无效值尽量用 nil 来表示,而不要用空table

、''、0、false 等等来表示,只有 nil 才是真正意义上的“

无效值”

Page 45: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Proper Tail Calls

在Lua中支持这样一种函数调用的优化,即不耗费任何栈空间的“尾调用消除”。我们可以将这种函数调用方式视为goto语句,如:

function f(x) return g(x) end

Page 46: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

形参 vs 实参

1. 实参多于形参,多出的部分被忽略

2. 形参多于实参,没被初始化的形参的缺省值为nil

function foo(a, b, c)

print(a, b, c)

end

foo('a', 'b', 'c', 'd') -- 'd' 被忽略

foo('a') -- 这时形参 b 和 c 都是 nil

Page 47: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Performace

Page 48: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Local Sharings

http {

lua_shared_dict lcache 64m;

...

}

dict.lua 模块介绍

http://wiki.nginx.org/HttpLuaModule#ngx.shared.DICT

Page 49: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Fastest Trim

function trim(s)

if type(s) == 'string' then

local match = string.match

return match(s,'^()%s*$') and '' or match(s,'^%s*(.*%S)')

end

return s

end

Page 50: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Memcached

1. https://github.com/agentzh/lua-resty-memcached

2. 自封装 memd.lua 模块介绍

Page 51: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Mysql

1. https://github.com/agentzh/lua-resty-mysql

2. 自封装 mysql.lua 模块介绍

Page 52: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Redis

https://github.com/agentzh/lua-resty-redis

自封装 redis.lua 模块介绍:

1)让 lua-resty-redis 的返回值变得规范

2)lazy connecting

3)添加 debug 功能和 log 功能

4)实现一些特殊的功能,比如 hclear

5)close 方法默认设置 set_keepalive

Page 53: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Block

Page 54: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

不需要在程序起始处声明所有局部(local)变量,在需要的时候才声明变量其实是好习惯,缩短变量的作用域在任何时候都是好的。

Page 55: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

List

list = nil

for v in values do

list = {next = list, value = v}

end

local l = list

while l do

print(l.value)

l = l.next

end

Page 56: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

跳转实例

=== TEST 13: rewrite args (not break cycle by default)

--- config

location /bar {

echo "bar: $uri?$args";

}

location /foo {

#set $args 'hello';

rewrite_by_lua '

ngx.req.set_uri_args("hello")

ngx.req.set_uri("/bar", true)

';

echo "foo: $uri?$args";

}

--- request

GET /foo?world

--- response_body

bar: /bar?hello

Page 57: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

How to “continue”?

local bContinue

for k, v in pairs(tbl) do

bContinue = false

......

if not bContinue then

......

if needToContinue then

bContinue = true

end

end

if not bContinue then

-- continue to do things

end

end

Page 58: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

elseif vs else if

if ... then

else

if ... then

end

end

if ... then

elseif ... then

end

Page 59: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

“select”

count = select(2, string.gsub(str," "," "))

-- string.gsub 第二个返回值是空格替换次数,select则选择该返回值,即 str 中空格的数量

Page 60: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

文件/IO

Page 61: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

1. io.write("hello","world") --写出的内容为helloworld

2. io.read("*all")会读取当前输入文件的所有内容

3. io.read(0)是一种特殊的情况,用于检查是否到达了文件的末尾。如果没有到达,返回空字符串,否则nil

Page 62: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Serialize

function serialize(o)

if type(o) == "number" then

io.write(o)

elseif type(o) == "string" then

--string.format函数的"%q"参数可以转义字符串中的元字符。

io.write(string.format("%q",o))

elseif type(o) == "table" then

io.write("{\n")

--迭代table中的各个元素,同时递归的写出各个字段的value。

--由此可以看出,这个简单例子可以支持嵌套的table。

for k,v in pairs(o) do

--这样做是为了防止k中包含非法的Lua标识符。

io.write(" ["); serialize(k); io.write("] = ")

serialize(v)

io.write(",\n")

end

io.write("}\n")

else

error("cannot serialize a " .. type(o))

end

end

Page 63: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Size and Seek

1. local f = assert(io.open(filename,"r"))

2. local current = f:seek() --获取当前位置

3. local size = f:seek("end") --获取文件大小

4. f:seek("set",current) --恢复原有的当前位置

Page 64: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

读取文件优化

下面是Shell中wc命令的一个简单实现:

local BUFSIZE = 8192

local f = io.input(arg[1]) --打开输入文件

local cc, lc, wc, = 0, 0, 0 --分别计数字符、行和单词

while true do

local lines,rest = f:read(BUFSIZE,"*line")

if not lines then

break

end

if rest then

lines = lines .. rest .. "\n"

end

cc = cc + #lines

--计算单词数量

local _, t = string.gsub(lines."%S+","")

wc = wc + t

--计算行数

_,t = string.gsub(line,"\n","\n")

lc = lc + t

end

print(lc,wc,cc)

Page 65: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Socket

Page 66: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Socket Connect

--用 ngx.socket.tcp 才能百分百支持 nonblocking

local sock = ngx.socket.tcp()

sock:settimeout(1000) -- one second

local ok, err = sock:connect("127.0.0.1", 11211)

local bytes, err = sock:send("flush_all\r\n")

if not bytes then

ngx.say("failed to send query: ", err)

return

end

local line, err = sock:receive()

if not line then

ngx.say("failed to receive a line: ", err)

return

end

ngx.say("result: ", line)

local ok, err = sock:setkeepalive(60000, 500)

if not ok then

ngx.say("failed to put the connection into pool with pool capacity 500 "

.. "and maximal idle time 60 sec")

return

end

Page 67: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Settimeout

sock:settimeout(1000)

ok, err = tcpsock:connect(host, port, options_table?)

sock:settimeout(1000)

bytes, err = tcpsock:send(data)

sock:settimeout(1000)

data, err, partial = tcpsock:receive(size) —读timeout是不会close掉连接的

local reader = sock:receiveuntil("\r\n--abcedhb")

sock:settimeout(1000)

while true do

……

end

ok, err = tcpsock:close()

Page 68: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Coroutine

Page 69: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

协程示例

协程的经典示例:“生产者-消费者”问题:

--消费者

function receive()

local status, value = coroutine.resume(producer) --消费

return value

end

--生产者

function send(x)

coroutine.yield(x) --挂起

end

--协程

producer = coroutine.create(

function()

while true do

local x = io.read() --产生新值

send(x)

end

end)

Page 70: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

cosocket 读取大数据

local sock, err = ngx.req.socket()

if not sock then

ngx.say("failed to get request socket: ", err)

return

end

sock:settimeout(10000) -- 10 sec timeout

while true do

local chunk, err = sock:receive(4096)

if not chunk then

if err == "closed" then

break

end

ngx.say("faile to read: ", err)

return

end

process_chunk(chunk)

end

Page 71: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Some Modules

Page 72: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

Serialize Module

—-使用 serialize 模块的函数对 PHP序列化的字符串进行反序列化,或者对lua

的 table 进行PHP序列化

require("lib.serialize")

local srlz = serialize

local unsrlz = unserialize

local luatable = unsrlz(php_serialized_string)

local php_serialized_string = serialize(luatable)

Page 73: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

luarocks

查看 luajit 版本:

ls /home/openresty/luajit/bin/luajit-2.0.2

wget http://luarocks.org/releases/luarocks-2.0.13.tar.gz

tar -xzvf luarocks-2.0.13.tar.gz

cd luarocks-2.0.13/

./configure --prefix=/usr/local/openresty/luajit \

--with-lua=/usr/local/openresty/luajit/ \

--lua-suffix=jit-2.0.2 \

--with-lua-include=/usr/local/openresty/luajit/include/luajit-2.0/

make build

sudo make install

PS:--lua-suffix 就是上面 luajit 的后缀

Page 74: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

lua-snappy

1. 从 https://github.com/forhappy/lua-snappy 下载并解压。

2. CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/home/openresty/luajit/include/luajit-2.0

export CPLUS_INCLUDE_PATH

3. 进入 lua-snappy-master 里面:

cd /lua-snappy-master ./sysconfig

vi Makefile

4. 加上 luajit 路径并加入到编译命令中:

CPPFLAGS=-fPIC -shared -Wall -g -O2 -I/home/openresty/luajit/include/luajit-2.0/

$(CC) $(CPPFLAGS) -o $@ -c $^

5. 编译安装:

make

6. 把 so 放到 lib 里面: cp snappy.so /home/openresty/lualib/

Page 75: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

模板技术

https://github.com/bungle/lua-resty-template

Page 76: OpenResty/Lua 70+ Advanced Programming Skills and Optimization tips

FAQ