在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):luastar/luastar开源软件地址(OpenSource Url):https://github.com/luastar/luastar开源编程语言(OpenSource Language):Lua 91.8%开源软件介绍(OpenSource Introduction):luastar1. luastar简介1.1 luastar是一个基于openresty的高性能高并发高效率http接口和web网站开发框架1.2 luastar在macOS和CentOS6.5+系统,openresty-1.7.10.2+环境测试通过。1.3 luastar主要特性:
2. luastar安装2.1 openresty 安装请参考官网介绍,https://openresty.org/cn/installation.html 建议安装目录:/usr/local/openresty 2.2 luastar 安装2.2.1 下载luastar从github下载luastar到本地目录,例如:/data/apps/luastar下。 2.2.2 修改luastar配置替换配置文件『/yourpath/luastar/conf/luastar*.conf』中的openresty安装路径和luastar存放路径,如下:
luastar/conf/目录下多个文件分别对应不同环境,例如luastar_dev.conf是开发环境的配置,luastar.conf是生产环境的配置 2.2.3 修改nginx配置修改openresty/nginx/conf/nginx.conf,引入luastar项目配置文件:
2.2.4 启动nignx/usr/local/openresty/nginx/sbin/nginx -c openresty/nginx/conf/nginx.conf 2.3 测试访问http://localhost:8001/api/test/hello http://localhost:8001/api/test/hello?name=haha 3 api开发3.1 luastar 项目结构
3.2 luastar 全局变量luastar 在初始化时,定义了几个常用的全局变量,在项目中可以直接使用,不用require引入,详情请参看:luastar/src/luastar_init.lua
3.3 缓存luastar提供了lua内存缓存,根据openresty机制,每个worker存有一份,所以在使用缓存前,需要先判断是否存在(即使初始化存储过),luastar中使用缓存存储了配置文件信息、bean信息、路由和拦截器信息等等。 例如:luastar/src/core/config.lua local _M = {}
local util_file = require("luastar.util.file")
function _M.getConfig(k, default_v)
-- 从缓存中获取配置信息
local app_config = luastar_cache.get("app_config")
if app_config then
-- 如果配置信息存在,返回
return app_config[k] or default_v
end
-- 如果配置信息不存在,初始化
ngx.log(ngx.INFO, "init app config.")
-- 加载配置文件
local app_config_file = ngx.var.APP_CONFIG or "/config/app.lua"
local config_file = ngx.var.APP_PATH .. app_config_file
app_config = util_file.loadlua_nested(config_file) or {}
-- 缓存配置信息
luastar_cache.set("app_config", app_config)
-- 返回结果
return app_config[k] or default_v
end
return _M 说明:内存缓存的好处在于支持所有的lua结构,没有限制。 如果需要缓存的内容比较简单或者可以序列化成json,可以考虑使用ngx.shared.DICT,实现全局共享。 3.4 luastar_context 上下文有些内容在init_by_lua阶段无法初始化,需要延后在content_by_lua阶段执行,不能放到初始化阶段里作为全局变量直接使用,所以放到了上下文中,详见:luastar/src/luastar/core/context.lua 3.4.1 初始化项目包路径和获取路由初始化项目包路径和获取路由已经在请问入口类中调用了,实际项目中应该不会调用,详见:luastar/src/luastar/luastar_content.lua 3.4.2 获取beanFactorybeanFactory是参考spring中的bean管理实现的一套lua bean,用于服务层,和require进来的对象相比,最大的区别是lua bean是用类实例化出来的对象,可以是单例的,也可以是多实例的,有自己的属性和方法。 -- 获取mysql服务
local beanFactory = luastar_context.getBeanFactory()
local mysql_util = beanFactory:getBean("mysql")
-- 创建链接
local mysql = mysql_util:getConnect()
-- 执行sql
local res, err, errno, sqlstate = mysql:query("select * from user")
ngx.log(logger.i(cjson.encode({
sql = sql,
res = res,
err = err,
errno = errno,
sqlstate = sqlstate
})))
-- 关闭链接
mysql_util:close(mysql) 3.4.3 获取msg项目中可能需要将输出的文案配置到配置文件中,便于做国际化或替换。 例如:demo/conf/msg.lua --[[
提示消息配置
普通消息
local message = luastar_context.getMsg("msg_live", "100001")
占位直接使用string的格式化方法,例如%s, %d等
local message = luastar_context.getMsg("msg_live", "100002"):format(100.00)
多级配置消息获取方法
local message = luastar_context.getMsg("msg_live", "100003", "001")
--]]
msg_pub = {
["100001"] = "错误1!", --
["100002"] = "金额不能超过%d元!", --
["100003"] = {
["001"] = "错误3-1!", --
["002"] = "错误3-2"
}, --
["199999"] = nil
}
msg_uc = {
["200001"] = "错误1!", --
["200002"] = "错误2!", --
["200003"] = "错误3!", --
["299999"] = nil
} 3.5 调试与日志3.5.1 调试luastar/openresty可以利用ZeroBraneStudio工具调试。 openresty使用ZeroBraneStudio调试步骤可参考链接:http://notebook.kulchenko.com/zerobrane/debugging-openresty-nginx-lua-scripts-with-zerobrane-studio luastar使用ZeroBranStudio调试步骤如下: 1、在包路径中增加ZeroBranStudio相关库文件,注意macos使用.dylib,centos上使用.so库
2、在需要调试的代码前后加上 require('mobdebug').start("127.0.0.1")
-- 调试代码
require('mobdebug').done() 3、断点,按ZeroBranStudio方法启动调试 3.5.2 日志如果觉得调试起来麻烦,日志就是最好的调试办法,简单高效(熟练后完全可以不需要调试)。 luastar直接使用ngx.log输出,之前也有用过第三方库 https://github.com/Neopallium/lualogging 在多worker模式中容易造成日志丢失。ngx.log的缺点是不能个性化按天输出(可以用脚本定时分割),输出大小有限制,不过一般也够用了。 luastar只是简单封装了固定输出request_id和简化的方法,不包装起来是为了直观的输出日志的位置
输出结果:
[2y6hNDFGd4Nxi7FE9UAP]是本次请求的request_id,便于在日志量大的情况下定位一次请求的所有日志。 3.6 项目配置一般项目都会有配置文件,在luastar项目中,配置文件放在demo/config/目录下,可以通过在luastar.conf文件中指定不同环境的配置,默认使用app.lua文件
配置文件的内容直接使用lua语法 --[[
应用配置文件
--]]
mysql = {
host = "10.1.1.2",
port = "3306",
user = "root",
password = "lajin2015",
database = "cms_admin",
timeout = 30000,
pool_size = 1000
}
redis = {
host = "10.1.1.4",
port = "6382",
auth = "lajin@2015",
timeout = 30000,
pool_size = 1000
}
_include_ = {
"/config/app_dev_a.lua",
"/config/app_dev_b.lua"
} include 是一个特殊的用法,支持配置文件嵌套引入。 配置文件的内容在代码中,可以通过luastar_config.getConfig来获取: local mysqlDataSource = luastar_config.getConfig("mysql")
local mysqlDataSourceHost = luastar_config.getConfig("mysql")["host"] 配置文件的内容也可以直接在bean.lua中使用, mysql = {
class = "luastar.db.mysql",
arg = {
{ value = "${mysql}" }
}
} 详情请参考bean的配置用法。 3.7 频次控制/路由/拦截器频次控制/路由/拦截器在demo/config/route.lua文件中配置 -- 频次限制
limit = { class = "com.luastar.demo.ctrl.test.limit", method = "limit" }
-- 全匹配路由,优先级高
route = {
{ "*", "/api/test/hello", "com.luastar.demo.ctrl.test.hello", "hello", { p1="v1", p2="v2" } },
{ "POST", "/api/test/pic", "com.luastar.demo.ctrl.test.hello", "pic" },
{ "*", "/api/test/mysql", "com.luastar.demo.ctrl.test.mysql", "mysql" },
{ "*", "/api/test/mysql/transaction", "com.luastar.demo.ctrl.test.mysql", "transaction" },
{ "GET,POST", "/api/test/redis", "com.luastar.demo.ctrl.test.redis", "redis" }
}
-- 模式匹配路由
route_pattern = {
{ "*", "/aaa/.*", "com.luastar.demo.ctrl.test.dispatcher", "aaa", { p1="v1", p2="v2" } }, -- aaa
{ "*", "/bbb/.*", "com.luastar.demo.ctrl.test.dispatcher", "bbb" }, -- bbb
{ "*", "/ccc/.*", "com.luastar.demo.ctrl.test.dispatcher", "ccc" }, -- ccc
{ "*", "/.*", "com.luastar.demo.ctrl.test.dispatcher", "other" } -- 默认
}
-- 拦截器配置,注:拦截器必须实现beforeHandle和afterHandle方法
interceptor = {
{
url = {
{ "*", "/api/.*", true }
},
class = "com.luastar.demo.interceptor.common"
}
} 3.7.1 频次控制频次限制需要配置实现的类和方法,方法需要返回布尔类型表示是否受限制,目前实现了ip限制,频次限制,单位时间内次数限制,基于 resty.limit 或 redis实现,resty.limit中的count实现需要openresty更高版本(支持dict:expire方法)。 参考: luastar/src/luastar/util/limit.lua demo/src/com/luastar/demo/ctrl/test/limit.lua 3.7.2 路由路由分为全匹配路由和模式匹配路由,全匹配优先级高,不支持路径取值(不建议),模式使用lua自带的模式。 路由是一个二维数组,每一行表示一个接口地址,第一列表示请求方式(*表示不限制,多个请求方式用逗号分隔,v1.4版本新增),第二列表示请求地址,第三列表示对应的处理类,第四列表示处理类中的方法,第五列表示自定义参数(以第三个参数传到处理类方法中) luastar默认给ctrl类请求处理方法传入了request/response对象(其他地方可通过ngx.ctx.request和ngx.ctx.response获取)和路由中第五列的自定义参数,用于处理输入和输出和路由扩展。 参考: demo/src/com/luastar/demo/ctrl/test/hello.lua 3.7.3 拦截器拦截器每一行表示一个拦截器(优先级取决于数组顺序),url为数组,支持同时拦截多个url,每个url是一个数组(第一列表示拦截的请求方法,*代表所有,第二列可以是模式的,取决于第三列),class代表拦截器实现,excludes表示该拦截器不处理的请求数组。 注:1.2 版本前后结构不同 拦截器要实现两个方法beforeHandle和afterHandle,beforeHandle必须返回布尔类型的结果,只要有一个拦截器返回false,则ctrl不会执行,beforeHandle可以返回第二个参数(字符串类型),用于返回false后的输出结果(返回true时忽略) 参考:demo/src/com/luastar/demo/interceptor/common.lua 3.8 lua bean 管理luastar实现了简化版的spring bean factory,默认将bean实例化后以单例模式(每个worker一份)存在缓存中,和require进来的对象相比,最大的区别是lua bean是用类实例化出来的对象,可以是单例的,也可以是多实例的,有自己的属性和方法。 3.8.1 定义beanbean在配置文件demo/config/bean.lua文件中配置,注意保证id的唯一性 --[[
id = { -- bean id
class = "", -- 类地址
arg = { -- 构造参数注入
{value/ref = ""} -- value赋值,ref引用其他bean
},
property = { -- set方法注入,实现set_${name}方法
{name = "",value/ref = ""}
},
init_method = "", -- 初始化方法,默认使用init()
single = 0 -- 是否单例,默认是1
}
--]]
-- mysql服务
mysql = {
class = "luastar.db.mysql",
arg = {
{ value = "${mysql}" }
}
}
-- redis服务
redis = {
class = "luastar.db.redis",
arg = {
{ value = "${redis}" }
}
}
-- 系统用户服务
userService = {
class = "com.luastar.demo2.service.system.userService"
}
-- 功能服务
funcService = {
class = "com.luastar.demo2.service.system.funcService"
}
-- 角色服务
roleService = {
class = "com.luastar.demo2.service.system.roleService"
}
-- 角色关系服务
userRoleRelationService = {
class = "com.luastar.demo2.service.system.userRoleRelationService"
}
-- 引入其他模块
_include_ = {
"/config/bean_uc.lua"
} bean配置文件也支持_include_引入其他配置的语法。 在类中定义的方法最好使用类的模式,存储私有变量,可以使用luastar框架中的class类定义。 参考: demo2/src/com/luastar/demo2/service/system/userService.lua |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论