如果你正在学 Lua 与 openresty,那你就一定知道在开发过程中,调试代码、单元测试是多么的麻烦。这里整理了一些 lua 开发的最佳实践。
简介
openresty 中 lua ide 调试,单元测试比较麻烦;lua 对库的管理比较散漫。在公司生产环境,一般没有外网环境,OpenResty 的安装和 lua 项目的部署都比较麻烦。
结合 Python 的一些经验,在这里整理一下自己对 Lua 的理解,以及 Lua 最佳实践。
OpenResty 安装
对于软件,使用编译方式安装比较好,比如 Ubuntu,apt-get 安装的包一般都会比较旧。如下介绍我的编译参数。这里需要自己下载自己的依赖包:naxsi, nginx-goodies-nginx-sticky-module-ng,pcre,openssl,zlib,并根据我的配置进行修改相应参数
1
2
3
4
5
6
7
8
9
10
11
12
|
./configure --prefix=$HOME/openresty \
--add-module=$HOME/openresty/setupfile/third/naxsi-0.55.3/naxsi_src \
--add-module=$HOME/openresty/setupfile/third/nginx-goodies-nginx-sticky-module-ng \
--with-pcre=$HOME/openresty/setupfile/depency/pcre-8.41 \
--with-openssl=$HOME/openresty/setupfile/depency/openssl-1.0.2k \
--with-zlib=$HOME/openresty/setupfile/depency/zlib-1.2.11 \
--with-http_v2_module \
--with-http_sub_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-cc-opt=-O2 \
--with-luajit
|
安装 luarocks
1
2
3
4
5
6
7
8
9
10
|
./configure --prefix=$HOME/openresty/luajit \
--with-lua=$HOME/openresty/luajit \
--lua-suffix=jit \
--with-lua-include=$HOME/openresty/luajit/include/luajit-2.1
--prefix 设定 luarocks 的安装目录
--with-lua 则是系统中安装的 lua 的根目录
--lua-suffix 版本后缀,此处因为openresyt的lua解释器使用的是 luajit ,所以此处得写 jit
--with-lua-include 设置 lua 引入一些头文件头文件的目录
make build && make install
|
lua 面向对象
lua 借助 table 以及 metatable 的概念进行 oo 的。这里摘了一个博客的代码,看起来还可以。以后可以使用这个。Lua 中实现面向对象。
这里要说一下 lua 中.运算和:的区别,a={};a.fun(a, arg) 等价于 a:fun(arg),其实就是:可以省略 self 参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
local _class={}
function class(super)
local class_type={}
class_type.ctor=false
class_type.super=super
class_type.new=function(...)
local obj={}
do
local create
create = function(c,...)
if c.super then
create(c.super,...)
end
if c.ctor then
c.ctor(obj,...)
end
end
create(class_type,...)
end
setmetatable(obj,{ __index=_class[class_type] })
return obj
end
local vtbl={}
_class[class_type]=vtbl
setmetatable(class_type,{__newindex=
function(t,k,v)
vtbl[k]=v
end
})
if super then
setmetatable(vtbl,{__index=
function(t,k)
local ret=_class[super][k]
vtbl[k]=ret
return ret
end
})
end
return class_type
end
|
基本编码规范 设计
可以参考 OpenResty 的最佳实践,平时用起来,大部分跟 c 的风格差不多吧。主要是所使用的代码风格要统一。
包管理
lua 下有两个包管理系统,LuaDist 和 LuaRocks
单元测试
- 重点 如下方法请在命令行中使用类似
curl localhost/unittest进行测试,浏览器中看会很痛苦
- OpenResty 最佳实践-单元测试给出一种方法。我的处理方法是,在 nginx.conf 中的 server 中建一个单独的 location,content_by_lua_file 设置 unittest.lua。公司用的 verynginx,所以我把此配置放到了 router.lua 中(当然配置方法类似,这个很容易研究,就不放到这里了)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
-- file: unittest.lua
local _M = {}
local csrf_test = require("test.test_csrf")
local tmp_test = require("test.tmp_test")
function _M:run_unittest()
csrf_test:run()
end
return _M
-- file: test_csrf.lua
local iresty_test = require("resty.iresty_test")
local json = require("json")
local config = require("config")
local csrf_config = require("csrf_config")
local token = require("token")
local tabletls = require("tabletls")
local tb = iresty_test.new({unit_name="test_csrf"})
local function assert_eq(wanted, real, msg)
if wanted ~= real then
error(msg or "error", 2) -- 请注意参数 2
end
end
local function assert_not_eq(wanted, real, msg)
if wanted == real then
error(msg or "error", 2)
end
end
function tb:test_geturl()
assert_eq("/unittest", ngx.var.uri, "the unittest url changed")
end
function tb:run_unittest()
tb:run()
end
return tb
|
- 如上有一个很有意思的地方,
error(msg or "error", 2),其中的 2 有些讲究,表示返回调用函数所在行,还有 0(忽略行号),1(error 调用位置行号)
- 性能测试 代码覆盖率 API 测试等,都可以去OpenResty 最佳实践中找,配置很简单。
远程调试 OpenResty
- 对于此部分,对于有些人来说,使用日志就已经足够了。可对于有些时候,在代码中太多的日志有不利于维护。这里自己要尽力做好日志和调试的平衡吧。
- 此调试方法适用于 win linux osx
- 先贴这里用到的 luaIDE 地址:ZeroBraneStudio
- 如下为安装步骤:
- 下载这个项目,ZeroBraneStudio,解压可以直接用【调试方法在下载好的文件中 README.md 中有相应的链接】
- 启动 ZBS,Project -> Start Debugger Server
- 复制/lualibs/mobdebug/mobdebug.lua -> nginx lua path,
- 复制/lualibs/socket.lua -> nginx lua path,
- 复制/bin/clibs/socket/core -> socket 设为 nginx lua cpath(调试时候,使用的是 require(“socket.core”)形式导入包。这里需要注意 core 文件后缀,win 是 dll,linux 是 so,)
- nginx 配置好,将如上依赖加到 nginx.conf 中,让 lua 可以找到这些文件即可
- 创建需要调试的 lua 文件
1
2
3
4
5
|
require('mobdebug').start('192.168.1.22')
local name = ngx.var.arg_name or "Anonymous"
ngx.say("Hello, ", name, "!")
ngx.say("Done debugging.")
require('mobdebug').done()
|
注:start()呼叫需要运行 IDE 的计算机的 IP 。默认情况下使用“localhost”,但是由于您的 nginx 实例正在运行,因此您需要指定运行 IDE 的计算机的 IP 地址(在我的例子中 192.168.1.22)
- 在 ide 中打开需要调试的如上 lua 文件
- Project -> Project Directory -> Set From Current File。
- 此时,打开浏览器,访问需要此文件处理的链接
- 此时开始调试

- 注:在最下侧有 Remote console,在这里可以执行任何 ngx lua 语句
- 如上流程没有截图,或者没有说清楚,可以来这里
nginx 一些技巧
1
|
lua_package_path '$prefix/lua_script/?.lua;;';
|
资料