【问题背景】
前几天,我们上线了“基于’Nginx + Lua‘实现的统一权限校验功能”。该功能需要Nginx守护线程定期地从MySQL加载“合作方数据”,我们直接在Lua文件里写死了MySQL等配置信息(硬编码),然后通过一个“中间配置文件”手动修改来针对不同的部署环境选择不同的数据源。
这里有个坑:当开发和运维都忘记修改这个“中间配置文件”时,部署到不同的环境指向的数据源确一样的,会导致验证失败错误。默认是指向线上数据源,当我们部署完线上之后,确认一切正常之后,就立马着手部署测试联调环境,结果都为了要修改这个“中间配置文件”(部署完成后,没有通过本地curl确认,其实这样可以减少犯错的机会!)。下午刚把所有相关的环境部署替换完成,结果晚上就有运营接收到客户(“挖财”)的API验证失败错误投诉,因为下午同样的调用还是正常的。
【线上问题紧急处理】
虽然,当时接到运营反馈后,leader结合下午的功能上线动作,很快就确认可能由于刚上线的“统一权限校验功能”,马上先回滚了测试联调环境的Nginx配置,保证客户可以联调。(后来确认问题根源确实是由于数据源加载错误引起,需要加载测试联调环境的数据源,结果却加载了线上数据源)
【解决方案】
从上面这个问题可以看到,“如果依赖人的手动修改才能做正确的事情”是不现实的,应当尽可能地避免这样的情况出现。所以,针对以上问题,我们就联想到能不能通过类似“Spring XML与Properties”分离解耦的技术来实现,然后通过类似Maven预编译来自动生成相关的配置文件。针对以上想法,我做了“通过Shell脚本来组装Lua配置模板文件与配置属性文件来生成配置文件”的尝试,上苍不负有心人,最终搞定这事了。方案步骤,如下:
- 定义“Lua配置模板文件”
- 针对不同的部署环境,定义相关的“配置属性文件”
- 通过Shell脚本来生成最终的配置文件(当然这一步也可以实现自动化)
具体实施步骤,如下:
1. 查看config-generator.sh是否具有“执行权限”
ll -h nginx/lua/bin/config-generator.sh
2. 若config-generator.sh没有“执行权限”,则授予其“执行权限”
chmod a+x nginx/lua/bin/config-generator.sh
3. 根据“配置模板”、“配置属性文件”和“部署环境”来生成配置文件(config.lua)
nginx/lua/bin/config-generator.sh -e test -c /usr/apps/nginx/lua/lib/cn/fraudmetrix/ngx/
or
nginx/lua/bin/config-generator.sh -e test -c nginx/lua/lib/cn/fraudmetrix/ngx/
【前后方案实现】
原实现
中间配置文件
-- in development --return require "cn.fraudmetrix.ngx.config.config-dev" -- in production return require "cn.fraudmetrix.ngx.config.config-prod"
开发环境的配置
-- config value local config = { version = "1.1", mysql = { host = "127.0.0.1", port = 3306, database = "dev", user = "dev", password = "123456", max_packet_size = 1024 * 1024, -- 1M mysql返回包大小上限 timeout = 500, -- ms idle_timeout = 60000, -- ms pool_size = 4 }, cache = { -- 缓存大小上限 partner = 10000, -- 合作方 upstream = 100 -- 上游 }, timer = { -- timer执行周期 partner = 3600, -- s }, } return config
现在实现
完整的代码见附件~~~
Lua配置模板文件
-- config value -- 【变量占位符替换】若替换值为“字符串”类型的,以单引号(\')定义;若替换值为“数值”类型的,以双引号(\")定义。 local config = { version = '1.1', mysql = { host = '$mysql_host', port = "$mysql_port", database = '$mysql_database', user = '$mysql_user', password = '$mysql_password', max_packet_size = "$mysql_max_packet_size", -- 1M mysql返回包大小上限 timeout = "$mysql_timeout", -- ms idle_timeout = "$mysql_idle_timeout", -- ms pool_size = "$mysql_pool_size" }, cache = { -- 缓存大小上限 partner = "$cache_partner_max_num", -- 合作方 upstream = "$cache_upstream_max_num" -- 上游 }, timer = { -- timer执行周期 partner = "$timer_partner_period", -- s }, } return config
测试环境的配置属性文件
# 配置属性名称定义以下划线("_")分割,不能以点号(".")分割(因为在Shell脚本中,点号(".")是一个特殊字符) # MySQL mysql_host=127.0.0.1 mysql_port=3306 mysql_database=test mysql_user=test mysql_password=123456 # 风险点:随着”合作方“接入增多,未来”合作方“MySQL加载的数据大小可能超过该值! mysql_max_packet_size=1024*1024 mysql_timeout=500 mysql_idle_timeout=60000 mysql_pool_size=4 # Local Cache # 风险点:随着”合作方“接入增多,未来”合作方“的数量可能超过该值! cache_partner_max_num=10000 cache_upstream_max_num=100 # Timer timer_partner_period=3600
Shell解析脚本
#!/usr/bin/env bash # ----------------------------------------------------------------------------- # Generates 'Configuration' file of Lua (config.lua) automatically. # ----------------------------------------------------------------------------- usage() { echo "Usage:" echo " sh config-generator.sh [-e app_deploy_env] [-c config_file_dir]" echo "" echo "Description:" echo " -e application deploy environment. The option value is prod, test or dev." echo " -c configuration file directory for Lua (/absolute/path/to/lua/config)." echo "" echo "Example:" echo " nginx/lua/bin/config-generator.sh -e test -c /usr/apps/nginx/lua/lib/cn/fraudmetrix/ngx/" echo " nginx/lua/bin/config-generator.sh -e test -c nginx/lua/lib/cn/fraudmetrix/ngx/" echo "" exit 1 } # 默认是“生产环境” app_deploy_env="prod" # “配置文件”默认放在“当前目录下” config_file_dir="." # 1. 接收“参数” while getopts ":e:c:h" arg do case $arg in e) app_deploy_env="$OPTARG";; c) config_file_dir="$OPTARG";; h) usage;; ?) usage;; esac done # 2. get 'config_file' # 兼容“path”与“path/”的情况 config_file_dir_last_char="${config_file_dir: -1}" if [ "$config_file_dir_last_char"x = "/"x ]; then # "path/" + "config.lua" config_file="$config_file_dir"config.lua else # "path" + "/config.lua" config_file="$config_file_dir"/config.lua fi # 兼容“path”与“/path”(相对路径与绝对路径)的情况 config_file_dir_first_char="${config_file_dir:0:1}" if [ "$config_file_dir_first_char"x != "/"x ]; then # relative path cur_prg_dir=`pwd` config_file="$cur_prg_dir"/"$config_file" fi # 3. 根据“配置模板”、“配置属性文件”和“部署环境”来生成“配置内容” # resolve links - $0 may be a softlink (解析链接 - $0 可能是一个“软链接”) # 执行程序 PRG="$0" while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`/"$link" fi done # ”执行程序“所在的”相对根目录“ PRGDIR=`dirname "$PRG"` # 转换为”绝对根目录“ PRGDIR=`readlink -f "$PRGDIR"` config_template_file="$PRGDIR"'/../config/config-template.lua' config_properties_file="$PRGDIR"/../properties/config-"$app_deploy_env".properties # 执行“配置模板解析器” CONFIG_PARSER_EXECUTABLE="$PRGDIR"/config-parser.sh if [ ! -x "$CONFIG_PARSER_EXECUTABLE" ]; then `sudo chmod a+x "$CONFIG_PARSER_EXECUTABLE"` fi exec "$CONFIG_PARSER_EXECUTABLE" "$config_file" "$config_template_file" "$config_properties_file"
#!/usr/bin/env bash # ----------------------------------------------------------------------------- # Generates 'config.lua' by 'config-template.lua' and 'config-${mode}.properties'. # ----------------------------------------------------------------------------- config_file="$1" config_template_file="$2" config_properties_file="$3" # source the properties . "$config_properties_file" # replace the placeholder eval "echo \"$(<$config_template_file)\"" > "$config_file" echo "Generates 'Configuration' file of Lua to '$config_file'"
相关推荐
lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问文件哈哈哈lua脚本问...
本文将深入探讨如何使用和配置这些文件来提升你的Lua开发体验。 首先,`hello.lua` 是一个示例Lua脚本,它可能包含了简单的打印语句或其他教学内容,用于展示如何在Scite中运行和调试Lua代码。当你在Scite中打开这...
接下来,我们谈谈如何使用protobuf定义来生成Lua和Go代码: 1. **编写.proto文件**: 这是protobuf的数据结构定义文件。例如,你可以定义一个简单的消息类型: ``` syntax = "proto3"; message Person { string ...
"luac解密在线"可能是指存在一些在线服务或工具,允许用户上传LUAC文件并在线进行解密和反编译。这种方式方便快捷,但可能涉及版权和安全问题,因此应谨慎使用。 "luac4加密"指的是LUAC的特定版本——LUAC 4,它...
LUA(Lua Programming Language)是一种轻量级的脚本语言,常用于游戏中的扩展和自定义,因其简洁的语法和易于学习的特点,在CSGO社区中被广泛使用。 LUA文件是LUA语言编写的源代码文件,通常包含了一系列函数、...
总结,Android Lua脚本文件为我们提供了一种灵活、高效的手段来扩展Android应用的功能,通过AndroLua这样的工具,我们可以轻松地编写和运行Lua脚本,同时利用Android API实现丰富的功能。无论你是游戏开发者还是自动...
最近比较迷恋lua脚本,用C写,改动起来有些麻烦,因此就用lua写了一个,觉得跨平台,省事,可以配置目录,文件名。并邮件通知,呵呵. 记得安装luafilesystem包,如果是win平台,好像自带,生产系统是linux,因此需要...
"游戏脚本设计与实现" ...从提供的游戏脚本实例中,我们可以了解到游戏脚本设计的基本结构、游戏任务的设计、游戏机制的实现、游戏逻辑的编写、lua语言在游戏脚本中的应用、游戏脚本的优化和游戏脚本的测试等知识点。
Lua是一种轻量级的脚本语言,常用于游戏开发、嵌入式系统和服务器配置等领域。在编程过程中,为了优化代码性能,理解脚本的执行情况是至关重要的。"lua脚本执行行数和次数统计Dll"就是这样一个工具,它能够帮助...
Lua 是一个小巧的脚本语言。...不仅仅作为扩展脚本,也可以作为普通的配置文件,代替XML,Ini等文件格式,并且更容易理解和维护。 Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译,运行。
lua 读写ini文件
2. `bool loadConfig(const std::string& filePath)`: 加载指定路径的Lua配置文件,使用`luaL_dofile`或`luaL_loadfile`加载脚本。 3. `bool readTable(const std::string& tableName)`: 读取Lua中指定名称的table,...
LUA脚本是一种轻量级的、嵌入式的脚本语言,因其简洁的语法和高效性能,被广泛应用于游戏开发、服务器配置、自动化任务等多个领域。LUA脚本支持库则是为了扩展LUA的功能,提供更丰富的API和工具,使得开发者能够更...
标题中的“Lua编译成exe的工具”指的是将用Lua编程...总的来说,lua2exe是Lua开发者的一个实用工具,它可以将 Lua 脚本打包成独立的可执行文件,便于分发和执行,但同时也需要考虑文件大小、源代码安全和调试等问题。
为了在STM32F103上运行Lua,首先需要一个经过优化的Lua编译版本,可能需要使用交叉编译工具链来生成适合微控制器的二进制代码。然后,需要在STM32的存储器中安排lua解释器和脚本的存储位置,通常包括RAM和Flash。...
luaQrcode是这样一个工具,它允许开发人员使用Lua编程语言来生成二维码,从而扩展了Lua的应用场景,特别是在嵌入式系统、游戏开发等领域。本文将详细介绍luaQrcode的工作原理、使用方法以及与之相关的技术。 **1. ...
“angel script和C++整合上要比lua方便 性能上不会比lua差(都是编译运行) 错误定位上也比lua强.txt”提到了另一种脚本语言AngelScript,并对比了它与Lua在与C++集成、性能和错误调试方面的优劣。尽管Lua通常被认为...
CSGO 罗技脚本 LUA文件导入即可 方便大家 有些XML不会的可以用这个 导入后大小写灯负责载入脚本 鼠标4号键开启 5号键关闭 CSGO AK专用
Lua是一种轻量级的、解释型的、动态类型的脚本语言,它的设计目标是易于学习、使用和嵌入。Lua语法简洁,且提供了丰富的库支持,因此在游戏开发、自动化工具以及配置文件等领域广泛应用。 要让VS2010项目能够调用...