【问题标题】:(Too) complex configuration management (Java properties)(太)复杂的配置管理(Java属性)
【发布时间】:2016-08-18 12:18:54
【问题描述】:

我在一家拥有(过于)复杂的配置管理流程的公司工作:

  • 在每个模块中都有一个 application.properties 文件。开发人员的属性如下:database.host = localhost
  • 在其他环境中更改的属性保存在覆盖属性文件夹(对于每个模块)中的 application.properties 文件中,例如:database.host=@dbhost@
  • 有一个 default-deployment.properties 文件,其中包含其他环境的默认值,例如:database.HOST=noValueConfigured.DB_HOST
  • 带有DATABASE_ HOST=@configure.DB_HOST@ 的 postconfigure.properties 文件

仅当属性值取决于环境时才需要这些文件(对于开发、测试、实时而言是不同的)。

  • 最后有一个 Excel 文档,其中包含每个环境的工作表和一行,例如:configure.DB_HOST - a comment ... - 127.0.0.1(仅作为示例)。 Excel 负责为 rpm 包生成正确的属性文件。

这个过程不仅复杂而且容易出错。 如何简化/改进?

该方法应该与 Spring DI 兼容。

【问题讨论】:

    标签: java spring properties properties-file configuration-management


    【解决方案1】:

    我将从一个主配置文件开始,然后生成要开始的属性文件。

    最终,您可以拥有一组可以部署在所有环境中的属性文件,例如

    database.host = localhost
    database.host.prod = proddb1
    database.host.uat = uatdb1
    

    即最后使用 environment/host/region/service 作为搜索路径。这样做的好处是您可以看到环境之间的差异。

    你可以像这样实现这个收集

    public class SearchProperties extends Properties {
        private final List<String> searchList;
    
        public SearchProperties(List<String> searchList) {
            this.searchList = searchList;
        }
    
        @Override
        public String getProperty(String key) {
            for (String s : searchList) {
                String property = super.getProperty(key + "." + s);
                if (property != null)
                    return property;
            }
            return super.getProperty(key);
        }
    

    你可以这样构造

    Properties prop = new SearchProperties(Arrays.asList(serverName, environment));
    

    这样,如果该服务器有匹配项,它将覆盖将覆盖默认值的环境。

    在 Java 8 中你可以这样做

    public String getProperty(String key) {
        return searchList.stream()
                .map(s -> key + "." + s)
                .map(super::getProperty)
                .filter(s -> s != null)
                .findFirst()
                .orElseGet(()-> super.getProperty(key));
    }
    

    【讨论】:

    • 如果属性值不依赖于环境(意味着它们在 dev、test 和 live 上是相同的),那么它们只是被输入到 application.properties 文件中而不是其他任何地方。只有当它们依赖于环境时,它们才必须在所有这些文件中指定。
    • @mosquito87 或者您可以按照我的建议将它们全部放在同一个文件中,这样您就可以看到每个应用程序在不同环境之间的差异并且只有一个文件。
    • 好的,这是一个想法,我会建议。谢谢。
    • @mosquito87 我已将代码添加到我的答案中。
    • 谢谢。我们将 Spring 用于 DI。这个策略与 Spring 兼容吗?
    【解决方案2】:

    应该只有一个文件,即使它有很多属性。此外,每个功能应该只有一个属性,例如 database.host,而不是 database.host 和 database_host,或类似的东西。

    您需要为此类和每个属性创建层次结构,以便知道哪个是用户。例如,如果 database.host 有一些 head 全局值,则它应该用于该属性。如果不是,请检查层次结构中的下一个级别,例如特定环境(例如生产价值)。如果不存在,请检查下一个级别,例如本地或测试级别。对于底层,有一个默认值。这样,您就拥有了两个维度的消费属性,因此大大减少了出错的机会。

    在我曾经工作过的一家公司中,我们有自动部署程序来处理此类级别设置,我们只需在其网站上为我们想要的级别设置变量,然后它会从上到下进行设置。我们从来没有遇到过这样的设置问题,我们在 app.properties 文件中会有超过 50 个变量。

    【讨论】:

      【解决方案3】:

      如果不考虑之前 cmets 中提到的所有重新设计方法,您可以将所有复杂性包装到 Tomtit 任务管理器中,这对于这些类型的任务很有用。

      只需创建属性文件templates 并使用environments 填充它们

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-07
        • 1970-01-01
        • 2014-06-26
        • 1970-01-01
        • 1970-01-01
        • 2012-09-20
        • 2011-03-01
        相关资源
        最近更新 更多