浏览 881
apollo是我们常用的修改nginx配置工具,但是为达到自动更新的目标,还需要写个小程序,实现配置的修改和更新,通常会采用java写个小程序直接实现nginx配置修改.如下图:
但是在实际应用过程中,我们的nginx配置信息需要调整,且配置信息不仅仅是一个人在维护,通过java小程序的方式在协同的上存在问题,同时java程序存在开发、测试、发布等繁琐过程.
基于以上的考虑,推荐一个java+python语言相结合的方式,可以减少java开发、发布的工作,同时java应用只需要获取配置变更信息和调用python程序执行更新动作,逻辑简化,应用的稳定性有所提升,同时通过python可以实现更便捷的应用调整.如下图:
本文重点不解释发布的全过程,重点分享下如何用python实现读模版、模版参数修改、备份、覆盖、Reload以及状态判断的过程
# 全局变量定义和初始化
此处省略
# 参数获取
# -----------------------------
def init_common_param():
global dic_common_param
try:
dic_common_param = Properties(file_common_param).getProperties()
log.info("init_common_param success")
except Exception as e:
has_error = True
log.error("init_common_param:" + traceback.format_exc())
# -----------------------------
def init_cluster_info():
global dic_cluster_info
try:
dic_cluster_info = Properties(file_cluster_info).getProperties()
# 得到集群对应代理ip地址,配置文件中是以逗号分割的,转换为List
for k,v in dic_cluster_info["cluster_proxy_ip"].items():
dic_cluster_info["cluster_proxy_ip"][k] = dic_cluster_info["cluster_proxy_ip"][k].replace(' ','').replace(',',',').strip(',').split(',')
log.info("init_cluster_info success")
except Exception as e:
has_error = True
log.error("init_cluster_inf" + traceback.format_exc())
# -----------------------------
def init_app_param():
global dic_app_param
try:
dic_app_param = Properties(file_app_param).getProperties()
log.info("init_app_param success")
except Exception as e:
has_error = True
log.error("init_app_param:" + traceback.format_exc())
# -----------------------------
def init_switch():
global dic_switch
try:
dic_switch = Properties(file_switch).getProperties()
log.info("init_switch success")
except Exception as e:
log.error("init_switch:" + traceback.format_exc())
# -----------------------------
def init_release():
global dic_release
try:
dic_release = Properties(file_release).getProperties()
log.info("init_release success")
except Exception as e:
log.error("init_release:" + traceback.format_exc())
# -----------------------------
# 临时存放应用灰度和所有环境的变量值
dic_app_param_temp = {}
# 生成应用在nginx中的配置
def create_app_nginx_config():
# 生成nginx配置时临时存放应用模板变量值的字典
# 注意该字段用于为nginx规则模板填充值,因为Nginx变量不允许包含-,所以此处将key包含的-字符自动替换为_
dic_app_tmpl_param = {}
# 生成应用配置文件输出路径,原有的先删除
if os.path.exists(app_config_out_path):
shutil.rmtree(app_config_out_path,True)
os.mkdir(app_config_out_path)
for app in dic_common_param["app_names"].values():
init_gray_and_env_proxy_value(app)
# 清空模板变量字段以便重新赋值
dic_app_tmpl_param.clear()
# 将当前服务名加入参数字典
dic_app_tmpl_param["app_name"] = app
dic_app_tmpl_param["app_port"] = dic_common_param["app_ports"][app]
# location默认为/
dic_app_tmpl_param["location"] = "/"
# 将环境与域名地址对应关系字典整合到目标参数字典中
for k,v in dic_app_param_temp.items():
dic_app_tmpl_param[k.replace("-","_")] = v
# 将common.param中灰度变量添加到参数字典
for k,v in dic_common_param.items():
dic_app_tmpl_param[k.replace("-","_")] = v
rule_tmpl = DEFAULT_RULE + ".tmpl"
stickySession = "false"
if dic_app_param.has_key(app):
# 允许自定义location
dic_app_tmpl_param["location"] = dic_app_param[app].get("location", "/")
# 将其他自定义参数加入参数字典
list_default_params = ["location", "rule", "stickySession", "upstream"]
for pmName, pmValue in dic_app_param[app].items():
if pmName not in list_default_params:
dic_app_tmpl_param[pmName.replace("-","_")] = pmValue
rule_tmpl = dic_app_param[app].get("rule", DEFAULT_RULE) + ".tmpl"
else:
# 全部采用默认配置
log.info("应用:" + app + "没有配置参数,全部使用默认值")
# 输出服务的nginx配置到临时目录
with open(rule_template_path + rule_tmpl, 'r') as f:
s = Template(f.read())
with open(app_config_out_path + app + ".conf", 'w') as fw:
fw.write(s.safe_substitute(dic_app_tmpl_param))
log.info("生成应用:" + app + "配置到临时目录成功")
# 将原有中心文件夹名加上当前时间并移动到nginx配置下的bak文件夹
def backupCurNginxConf():
bakPath = nginx_config_path + "bak/"
if not os.path.exists(bakPath):
os.mkdir(bakPath)
if os.path.exists(nginx_config_path + center_name):
shutil.move(nginx_config_path + center_name, bakPath + center_name + "." + datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
#将新配置移动到nginx配置路径
def moveNewCenterConfigToNginx():
shutil.move(app_config_out_path, nginx_config_path + center_name)
#reload nginx
def reload_nginx():
ret = subprocess.Popen('sudo systemctl reload openresty',shell=True,stderr=subprocess.PIPE)
ret.wait()
if ret.returncode != 0:
log.error("reload nginx失败,nginx使用原有配置.中心:" + center_name)
exit(7)
#主程序
def main(argv = sys.argv[1:]):
global root_path
global center_name
global nginx_config_path
root_path = cur_file_dir().rstrip('/') + "/"
center_name = argv[0].rstrip('/')
nginx_config_path = nginx_config_path.rstrip('/') + "/"
try:
init()
init_common_param()
init_cluster_info()
init_app_param()
init_switch()
init_release()
except Exception as e:
log.error("初始化配置异常,网关无法生成,nginx使用原有配置.中心:" + center_name + ", error:" + traceback.format_exc())
exit(1)
try:
create_app_nginx_config()
log.info("生成nginx配置到临时目录成功")
except Exception as e:
log.error("生成nginx配置异常,网关无法生成,nginx使用原有配置.中心:" + center_name + ", error:" + traceback.format_exc())
exit(2)
try:
backupCurNginxConf()
log.info("备份nginx现有配置成功")
except Exception as e:
log.error("备份nginx现有配置失败,取消新配置应用,nginx使用原有配置中心:" + center_name + ", error:" + traceback.format_exc())
exit(3)
try:
moveNewCenterConfigToNginx()
log.info("将新配置移动到nginx配置路径成功")
except Exception as e:
log.error("将新配置移动到nginx配置路径失败,网关无法生成,nginx使用原有配置.中心:" + center_name + ", error:" + traceback.format_exc())
exit(4)
try:
reload_nginx()
log.info("reload nginx成功")
# 发送reload成功通知
send_alert(5, "网关reload配置成功. 版本号:" + dic_release["release"] + ", 中心:" + center_name)
except Exception as e:
log.error("reload nginx失败,nginx使用原有配置.中心:" + center_name + ", error:" + traceback.format_exc())
exit(5)
if __name__ == '__main__':
main()
exit(0)
以上范例仅供参考,由于篇幅问题,省略参数初始化部分
按点赞数排序
按时间排序