博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多环境下的配置管理方案
阅读量:5942 次
发布时间:2019-06-19

本文共 2583 字,大约阅读时间需要 8 分钟。

  hot3.png

原文发布在

在开发中,我们需要面对各种各样的环境,开发环境、测试环境、生产环境……

并且,各个环境的参数和配置各不相同,比如数据库连接,服务器配置等。我们怎样在不同环境中调用正确的配置?

通过配置文件

这是一种常见的思路,通过创建多个配置文件,但根据命名区分,比如开发环境为develop-app.conf,测试环境为testing-app.conf,生产环境为production-app.conf

我们通过在系统中设置环境变量export ENV_MODE=develop等等。在读取配置文件时,根据环境变量读取响应的配置文件。

这个方式易于使用,深得大家喜爱。但这个方案在集群扩大的一定程度时,会遇到一下几个主要问题:

  • 假如有30~40个微服务需要连接数据库运行,这个量级在中小型团队中很常见了,如果我们需要更改数据库密码,我们不得不将数十个project逐个进行更新,非常不灵活。

  • 代码与配置掺杂在一起,代码是许多开发人员都可以看到的,也很容易泄露,而生产环境的各种秘钥应该只有少数人有权限能看到。这对系统的安全有重大影响。

  • 对于大量相同的配置(比如数据库配置),逻辑上我们应该存放在同一个地方,保证只有唯一可靠的数据来源。

对于这些问题,我们认为配置应该集中化管理。

集中化管理带来以下好处:

  • 各个服务间相同的配置只需要维护一分数据,保证唯一性
  • 各个环境的配置环境实现权限隔离,少数人拥有查看生产环境配置的权限
  • 更改配置将变得简单,不影响服务本身

最简单的方案就是存储在redis中。KV的存储方式天然适合关联配置文件。但要完整的使用整个方案,需要做一些准备。

集中式配置管理

我们的基本思路是:将配置文件的值替换为占位符,在系统启动时,相应的工具将根据占位符到redis中查询到实际的值,替换回配置文件。

最初的配置文件是这样:

{  "database_host":"127.0.0.1",  "database_port":3306}

现在我们的配置文件变成了这样:

{  "database_host":"{
{redis_hget "global.mysql" "host"}}", "database_port":{
{redis_hget "global.mysql" "port"}}}

读取配置

在启动时,我们通过这个工具:

这样读取配置文件

func main() {    data, _ := ioutil.ReadFile("./db.conf")    dbConf := DBConfig{}    if err := env_json.Unmarshal(data, &dbConf); err != nil {        fmt.Print(err)        return    }    fmt.Println(dbConf)}

这个工具,默认从/etv/env_string.conf读取redis的配置信息,当然你可以更改,更多细节参看说明文档。

在这个过程中,env_json首先会从/etv/env_string.conf读取到redis的配置信息。

典型的/etv/env_string.conf内容如下

{"storages": [{        "engine": "redis",        "options": {            "db": 0,            "password": "",            "pool_size": 10,            "address": "127.0.0.1:6379"        }    }]}

连接上redis后,以上面的例子来说,将执行hget global.mysql host以及hget global.mysql port,将取到的值通过模板替换,更新到配置文件中,得到一个正常的json文本,剩下的就是通过json库把json内容解码到结构体中。

到目前为止,我们实现了从redis中读取并替换配置,那么我们写入配置的时候呢?

假如我们有数十个服务,我们难道需要逐个去redis中设置吗?我们怎样把这个流程自动化?

写入配置

我们需要另一个工具:env_sync

我们存储配置文件其实是一个具体的git工程,比如开发环境是develop_env,生产环境是production_env,开发人员都可以编辑develop_env这个工程,少数人可以编辑production_env。

工程里的内容什么呢?

我们约定了这样的目录结构

develop_env	global.mysql    //this is folder         data       //this is file    components.accounts    	 data

在工程中,有一系列的文件夹,文件夹中有一个叫data的文件。这样的目录结构会被env_sync识别到,并转化成一系列的redis命令。

假如global.mysql文件夹下的data文件内容是

{  "host":"127.0.0.1",  "port":3306}

转化出来的命令是:

hset global.mysql host 127.0.0.1hset global.mysql port 3306

此过程与读取过程正好相反,同样的,env_sync也是从/etc/env_strings.conf读取配置信息。与读取工具保持了统一。

总结

整体来看我们需要做几个工作

  • 为各个环境维护一个配置文件project
  • 安装env_sync,便于同步配置文件到redis
  • 设置/etc/env_strings.conf
  • 更改读取配置文件的代码,兼容env_json

再结合自动化部署工具,每次配置文件有更新时,我们就在线上环境自动同步到redis。

更多

还有一种需求时,配置文件会动态变化,而我们不想重启服务就读取到配置文件,那你需要

这个工具可以实现对redis中数据的检测,如果数据发生变化,会触发回调,应用可以得到变化前后的值。

转载于:https://my.oschina.net/lubia/blog/684885

你可能感兴趣的文章
设计模式 - 迭代器模式(iterator pattern) 具体解释
查看>>
Codeforces554B:Ohana Cleans Up
查看>>
【java】jvm查看当前虚拟机堆大小限制
查看>>
python写入excel(xlswriter)--生成图表
查看>>
NetworkStream.write只能使用一次,后面再使用无效
查看>>
oracle进行字符串拆分并组成数组
查看>>
100多个基础常用JS函数和语法集合大全
查看>>
Java8 lambda表达式10个示例
查看>>
innerHTML outerHTML innerText
查看>>
kafka安装教程
查看>>
go语言基础
查看>>
LINQ to SQL活学活用(1):这要打破旧观念
查看>>
Spring boot 嵌入的tomcat不能启动: Unregistering JMX-exposed beans on shutdown
查看>>
【Windows】字符串处理
查看>>
Spring(十八):Spring AOP(二):通知(前置、后置、返回、异常、环绕)
查看>>
CentOS使用chkconfig增加开机服务提示service xxx does not support chkconfig的问题解决
查看>>
微服务+:服务契约治理
查看>>
save
查看>>
Android DrawLayout + ListView 的使用(一)
查看>>
clear session on close of browser jsp
查看>>