问题 我可以在DropWizard中拥有多个配置文件吗?


我想为DropWizard提供几个yaml文件。其中一个包含敏感信息,一个包含非敏感信息。

你能指点我的任何文档或示例如何在DropWizard中有多个配置吗?


12984
2018-02-25 18:50


起源



答案:


ConfigurationSourceProvider 是你的答案。

bootstrap.setConfigurationSourceProvider(new MyMultipleConfigurationSourceProvider());

以下是如何做到的 dropwizard默认情况下会这样做。您可以根据自己的喜好轻松更改它。

public class FileConfigurationSourceProvider implements ConfigurationSourceProvider {
    @Override
    public InputStream open(String path) throws IOException {
        final File file = new File(path);
        if (!file.exists()) {
            throw new FileNotFoundException("File " + file + " not found");
        }

        return new FileInputStream(file);
    }
}

5
2018-03-15 12:01



什么会 MyMultipleConfigurationSourceProvider 看起来像 ?我没有清楚了解它如何提供来自多个文件的数据。你介意解释一下吗? - Vic Seedoubleyew
我想这将是读取两个文件(硬编码或 | 分离的文件来自 path 参数),将它们合并为一个 InputStream 并返回。 - Natan
谢谢你的快速回复!如果我理解正确,这将产生重大影响,不是吗?例如,位于每个文件根目录的字段将最终位于“主重建”文件的根目录,可能会发生冲突。 - Vic Seedoubleyew
是的,如果预期任意yaml文件,这可能是一件危险的事情。我想在碰撞的情况下,将应用yaml解析器的规则,这可能是抛出异常或进行第一次/最后一次。在这种情况下,理想情况下,文件将具有单独的职责;即一个文件用于数据库,一个文件用于服务器配置,另一个用于自定义配置字段等。这应该以某种方式强制执行或记录良好。 - Natan


答案:


ConfigurationSourceProvider 是你的答案。

bootstrap.setConfigurationSourceProvider(new MyMultipleConfigurationSourceProvider());

以下是如何做到的 dropwizard默认情况下会这样做。您可以根据自己的喜好轻松更改它。

public class FileConfigurationSourceProvider implements ConfigurationSourceProvider {
    @Override
    public InputStream open(String path) throws IOException {
        final File file = new File(path);
        if (!file.exists()) {
            throw new FileNotFoundException("File " + file + " not found");
        }

        return new FileInputStream(file);
    }
}

5
2018-03-15 12:01



什么会 MyMultipleConfigurationSourceProvider 看起来像 ?我没有清楚了解它如何提供来自多个文件的数据。你介意解释一下吗? - Vic Seedoubleyew
我想这将是读取两个文件(硬编码或 | 分离的文件来自 path 参数),将它们合并为一个 InputStream 并返回。 - Natan
谢谢你的快速回复!如果我理解正确,这将产生重大影响,不是吗?例如,位于每个文件根目录的字段将最终位于“主重建”文件的根目录,可能会发生冲突。 - Vic Seedoubleyew
是的,如果预期任意yaml文件,这可能是一件危险的事情。我想在碰撞的情况下,将应用yaml解析器的规则,这可能是抛出异常或进行第一次/最后一次。在这种情况下,理想情况下,文件将具有单独的职责;即一个文件用于数据库,一个文件用于服务器配置,另一个用于自定义配置字段等。这应该以某种方式强制执行或记录良好。 - Natan


首先,您将在a中编写另一个yml文件路径 .yml

sample.yml

configPath: /another.yml

another.yml

greet: Hello!

只需使用SnakeYaml即可解决问题。

public void run(SampleConfiguration configuration, Environment environment) {
    Yaml yaml = new Yaml();
    InputStream in = getClass().getResourceAsStream(configuration.getConfigPath());
    AnotherConfig anotherConfig = yaml.loadAs(in, AnotherConfig.class);
    String str = anotherConfig.getGreet(); // Hello!
...
}

对于敏感信息,我认为使用环境变量是好的。

例如,使用dropwizard-environment-config
https://github.com/tkrille/dropwizard-environment-config


5
2018-02-26 15:49



这仅适用于自定义配置。但如果他们想让我们说 server 配置会影响dropwizard本身,然后它将无法正常工作。例如,可能想要混淆https证书的私钥密码。 - Natan


理想情况下,您应该通过将敏感信息或可配置数据放入其中来配置应用程序 环境变量而不是管理多个文件。请参阅配置中的十二个因子规则 http://12factor.net/config

要在Dropwizard中启用此方法,您可以使用在运行时使用环境变量覆盖您的配置 -Ddw 旗:

java -Ddw.http.port=$PORT -jar yourapp.jar server yourconfig.yml

或者您可以使用这个方便的添加: https://github.com/tkrille/dropwizard-template-config 将环境变量占位符放在配置中:

server:
  type: simple
  connector:
    type: http
    # replacing environment variables
    port: ${env.PORT}

上述两种解决方案都与Heroku和Docker容器兼容,其中环境变量仅在您运行应用程序时可用。


3
2018-03-25 22:22



不喜欢。你在哪里维护你的env vars?我的意思是,什么脚本设置它们?也许你会有一个启动应用程序的bash脚本,并首先设置所有env变量。现在您需要多个脚本,每个脚本对应一个环境(dev,qa,stage,prod等),其中每个脚本都有一组不同的env变量。这些脚本需要进行版本控制。但现在这些脚本只是配置文件。那时,为什么不只有一个只包含变量的文件(一个属性文件,或yaml,或者json,等等),并读取那些并跳过env var步骤? - Paul Rademacher
是的,需要设置env vars,但不是每次部署都是如此,就像你不需要在每次部署时都需要整个环境一样。您可以使用脚本,也可以使用配置工具 - yunspace
...例如Pupplet,Chef,Ansible等。最终,您的想法是将您的开发人员问题与Ops分开,以便不会将凭据检入源代码,可以独立审计安全性,并且可以在基础架构级别完成环境更改而不是挖掘每个源代码配置文件。共享变量文件也可以工作,但是如何更好?这意味着您的配置需要代码来读取每个服务中的变量,其中DW配置支持Env Var开箱即用。此外,Env Vars还可以使用Docker / Heroku等不可变容器的Continuous Delivery - yunspace
对于具有大量配置的应用程序,每个环境都会发生变化,那么系统变量将是一场噩梦。 - Ben George
大量基于文件的配置同样是噩梦般的。正如我所说的那样,重点是将开发与基础设施分开,而12因素方法是一个很好的选择。记住这个问题是关于Dropwizard,它往往是一个最小的,独立的微服务,而不是需要配置管理工具和全职配置器的整体应用程序 - yunspace