Vert.x Config

您可以使用 Vert.x Config 配置 Vert.x 应用。 它:

  • 提供多种配置语法(JSON,properties,Yaml(extension), Hocon(extension)……)

  • 提供多种配置中心,例如文件、目录、HTTP、git(extension)、Redis(extension)、 系统参数和环境变量。

  • 让您定义执行顺序以及覆盖规则

  • 支持运行时重新定义

概念

该库主要围绕:

Config Retriever 的实例化,并用于 Vert.x 应用。 它配置了一系列配置中心(Configuration store) Configuration store 定义了配置信息读取路径以及格式(默认JSON)

配置以 JSON 对象格式被接收。

使用 Config Retriever

要使用 Config Retriever, 则需要添加如下依赖:

  • Maven (在您的 pom.xml 文件):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'

以上工作完成之后,您第一件要做的事情就是实例化 ConfigRetriever

ConfigRetriever retriever = ConfigRetriever.create(vertx);

默认情况下,Config Retriever 可以使用下列配置中心进行配置 (按下列顺序):

  • Vert.x verticle config()

  • 系统参数

  • 环境变量

  • conf/config.json 文件。这个路径可以用 vertx-config-path 系统参数或者 VERTX_CONFIG_PATH 环境变量所覆盖。

您可以指定您自己的配置中心:

ConfigStoreOptions httpStore = new ConfigStoreOptions()
  .setType("http")
  .setConfig(new JsonObject()
    .put("host", "localhost").put("port", 8080).put("path", "/conf"));

ConfigStoreOptions fileStore = new ConfigStoreOptions()
  .setType("file")
  .setConfig(new JsonObject().put("path", "my-config.json"));

ConfigStoreOptions sysPropsStore = new ConfigStoreOptions().setType("sys");


ConfigRetrieverOptions options = new ConfigRetrieverOptions()
  .addStore(httpStore).addStore(fileStore).addStore(sysPropsStore);

ConfigRetriever retriever = ConfigRetriever.create(vertx, options);

如下可见更多关于覆盖规则和可用配置中心的细节信息。每一种配置中心都可以标记为 可选的(optional) 。 如果正在从一个可选的配置中心中获取(或处理)配置的时候,捕获到一个失败事件,那么这个失败事件会被日志所记录,但是执行过程并没有失败。 相反会返回一个空的 Json 对象(即:{})。 想要将一个配置中心标记为可选的,那么就使用 optional 属性:

ConfigStoreOptions fileStore = new ConfigStoreOptions()
  .setType("file")
  .setOptional(true)
  .setConfig(new JsonObject().put("path", "my-config.json"));
ConfigStoreOptions sysPropsStore = new ConfigStoreOptions().setType("sys");

ConfigRetrieverOptions options = new ConfigRetrieverOptions().addStore(fileStore).addStore(sysPropsStore);

ConfigRetriever retriever = ConfigRetriever.create(vertx, options);

获取 Config Retriever 示例后,可按如下所示 获取 配置:

retriever.getConfig(ar -> {
  if (ar.failed()) {
    // 获取配置失败
  } else {
    JsonObject config = ar.result();
  }
});

覆盖规则

配置中心的声明顺序非常重要, 因为它定义了覆盖顺序。对于冲突的key, 声明的配置中心会覆盖之前的。我们举个例子。 我们有两个配置中心:

  • A 提供 {a:value, b:1} 配置

  • B 提供 {a:value2, c:2} 配置

以 A,B 的顺序声明配置,最终配置应该为: {a:value2, b:1, c:2}

如果您将声明的顺序反过来(B,A),那么您会得到 {a:value, b:1, c:2}

使用配置

获取到的配置可用于:

  • 配置verticles,

  • 配置端口,客户端,location等等,

  • 配置Vert.x自身

本节给出几个使用示例。

配置一个单独的Verticle

以下示例代码可以放到 verticle 的 start 方法中。它获取了配置 (用默认配置中心),并且利用该配置创建了一个HTTP服务。

ConfigRetriever retriever = ConfigRetriever.create(vertx);
retriever.getConfig(json -> {
  JsonObject result = json.result();

  vertx.createHttpServer()
    .requestHandler(req -> result.getString("message"))
    .listen(result.getInteger("port"));
});

配置一组Verticles

以下示例用 verticles.json 文件中的配置创建了2个verticle

ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions()
  .addStore(new ConfigStoreOptions().setType("file").setConfig(new JsonObject().put("path", "verticles.json"))));

retriever.getConfig(json -> {
  JsonObject a = json.result().getJsonObject("a");
  JsonObject b = json.result().getJsonObject("b");
  vertx.deployVerticle(GreetingVerticle.class.getName(), new DeploymentOptions().setConfig(a));
  vertx.deployVerticle(GreetingVerticle.class.getName(), new DeploymentOptions().setConfig(b));
});

配置Vert.x自身

您也可以直接配置Vert.x自身。您需要一个临时Vert.x对象用来获取配置。 然后创建实际Vert.x实例:

Vertx vertx = Vertx.vertx();
// 创建 config retriever
ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions()
  .addStore(new ConfigStoreOptions().setType("file").setConfig(new JsonObject().put("path", "vertx.json"))));

// 获取配置
retriever.getConfig(json -> {
  JsonObject result = json.result();
  // 关闭vertx对象,我们再也用不到它了
  vertx.close();

  // 用获取到的配置创建一个新的Vert.x实例
  VertxOptions options = new VertxOptions(result);
  Vertx newVertx = Vertx.vertx(options);

  // 部署您的Verticle
  newVertx.deployVerticle(GreetingVerticle.class.getName(), new DeploymentOptions().setConfig(result.getJsonObject("a")));
});

向事件总线传播配置变更

当配置变化时,Vert.x Config 会通知您。如果您需要对这个事件做出响应,您需要自己实现这个逻辑。 例如,您可以下线/重新部署verticle或者向事件总线发送新的配置。 下列实例展示了后者的场景。它向事件总线发送新的配置。 与事件关联的 verticle可以监听这个address并更新自身:

ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions()
  .addStore(new ConfigStoreOptions().setType("file").setConfig(new JsonObject().put("path", "verticles.json"))));

retriever.getConfig(json -> {
  //...
});

retriever.listen(change -> {
  JsonObject json = change.getNewConfiguration();
  vertx.eventBus().publish("new-configuration", json);
});

可用的配置中心

Config Retriever 提供一系列的配置中心和配置格式。 更多可用的配置中心请参考本文后续介绍的扩展,您可以也自己实现.

配置的结构

每一个声明的数据配置中心必须要指定 类型(type) ,它也定义了 格式(format) 。 如果没有设置,默认用JSON。

一些配置中心要求额外的配置(比如路径……)。 这项配置需要用 setConfig 方法传入一个JSON 对象来指定。

文件

此配置中心仅从文件中获得配置。 他支持所有的格式。

ConfigStoreOptions file = new ConfigStoreOptions()
  .setType("file")
  .setFormat("properties")
  .setConfig(new JsonObject().put("path", "path-to-file.properties"));

path 配置项是必填项。

JSON

JSON配置中心按原样提供给定的JSON配置

ConfigStoreOptions json = new ConfigStoreOptions()
  .setType("json")
  .setConfig(new JsonObject().put("key", "value"));

这个配置中心仅仅支持JSON格式。

环境变量

这个配置中心将环境变量转换为用于全局配置的 JSON obejct

ConfigStoreOptions env = new ConfigStoreOptions()
  .setType("env");

这个配置中心不支持 format 配置项。 获取到的值默认会被传输到JSON兼容的结构当中(数字,字符串,布尔,JSON 对象和JSON 数组)。 如果要避免这种转换,则需要配置 raw-data 属性:

ConfigStoreOptions env = new ConfigStoreOptions()
  .setType("env")
  .setConfig(new JsonObject().put("raw-data", true));

您可以配置 raw-data 属性(默认为 false )。如果 raw-datatrue , 则不会对值进行转换。用 config.getString(key) 方法,您会得到原始值。 当操作大整型数时,这很有用。

如果您想选择一系列key值来导入,那么用 keys 属性。他将未选择的key值都过滤掉了。 key必须独立列出:

ConfigStoreOptions env = new ConfigStoreOptions()
  .setType("env")
  .setConfig(new JsonObject().put("keys", new JsonArray().add("SERVICE1_HOST").add("SERVICE2_HOST")));

系统参数

这个配置中心将系统参数转换为用于全局配置的 JSON 对象

ConfigStoreOptions sys = new ConfigStoreOptions()
  .setType("sys")
  .setConfig(new JsonObject().put("cache", false));

这个配置中心不支持 format 配置项。

您可以配置 cache 属性(默认为 true) 来决定是否在第一次访问时缓存系统参数而后不再重新加载他们。

您也可以配置 raw-data 属性(默认为 false )。如果 raw-datatrue , 则不会对值进行转换。用 config.getString(key) 方法,您会得到原始值。 当操作大整型数时,这很有用。

此外,亦存在有 hierarchical 属性(默认为 false)。如果 hierarchicaltrue, 则系统属性将被解析为嵌套的 JSON 对象,使用点分隔的属性名称作为 JSON 对象中的路径。

例子:

ConfigStoreOptions sysHierarchical = new ConfigStoreOptions()
  .setType("sys")
  .setConfig(new JsonObject().put("hierarchical", true));
java -Dserver.host=localhost -Dserver.port=8080 -jar your-application.jar

这将会读取系统属性为 JSON 对象相当于

{
 "server": {
   "host": "localhost",
   "port": 8080
 }
}

HTTP

这个配置中心从HTTP地址获取配置。 可以用任何支持的格式。

ConfigStoreOptions http = new ConfigStoreOptions()
  .setType("http")
  .setConfig(new JsonObject()
    .put("host", "localhost")
    .put("port", 8080)
    .put("path", "/A"));

他创建了一个带有 配置中心的配置 的Vert.x HTTP客户端(见下一小段)。 为了简化配置,您也可以用 host, portpath 属性来分别配置他们。 您也可以用 headers 属性来配置可选的HTTP请求头, timeout 属性配置超时时间(默认3000毫秒), followRedirects 属性来指定是否重定向(默认情况下为false)。

ConfigStoreOptions http = new ConfigStoreOptions()
  .setType("http")
  .setConfig(new JsonObject()
    .put("defaultHost", "localhost")
    .put("defaultPort", 8080)
    .put("ssl", true)
    .put("path", "/A")
    .put("headers", new JsonObject().put("Accept", "application/json")));

事件总线

这个配置中心从事件总线获取配置。 此种配置中心可以让您在本地和分布式组件之间传输配置。

ConfigStoreOptions eb = new ConfigStoreOptions()
  .setType("event-bus")
  .setConfig(new JsonObject()
    .put("address", "address-getting-the-conf")
  );

这个配置中心支持任何格式。

目录

这个配置中心和 文件 配置中心很相似, 但是它并不是去读单个文件,而是从一个目录中读取多个文件

这个配置中心必须要配置如下项:

  • 一个 path - 读取文件的根目录

  • 至少一个 fileset - 一个用于选择文件的对象

  • 对于properties文件,您可以用 raw-data 属性来禁止类型转换。

每一个 fileset 都包含:

  • 一个 pattern :一个Ant风格的pattern用于选择文件。 这个pattern应用于相对当前工作目录的相对路径。

  • 一个可选的 format ,它制定了文件的格式(每一个fileset可以用一个不同的format, 但是同一个fileset共用一个format)

ConfigStoreOptions dir = new ConfigStoreOptions()
  .setType("directory")
  .setConfig(new JsonObject().put("path", "config")
    .put("filesets", new JsonArray()
      .add(new JsonObject().put("pattern", "dir/*json"))
      .add(new JsonObject().put("pattern", "dir/*.properties")
        .put("format", "properties"))
    ));

ConfigStoreOptions dirWithRawData = new ConfigStoreOptions()
  .setType("directory")
  .setConfig(new JsonObject().put("path", "config")
    .put("filesets", new JsonArray()
      .add(new JsonObject().put("pattern", "dir/*json"))
      .add(new JsonObject().put("pattern", "dir/*.properties")
        .put("format", "properties").put("raw-data", true))
    ));

Properties 文件和原始数据

Vert.x Config可以读一个properties文件。当读取一个这样的文件,您可以传入 raw-data 参数来提醒Vert.x不要转换它的值。这在操作大整型数字时很有用。 这些值可以用 config.getString(key) 方法来获取。

ConfigStoreOptions propertyWithRawData = new ConfigStoreOptions()
  .setFormat("properties")
  .setType("file")
  .setConfig(new JsonObject().put("path", "raw.properties").put("raw-data", true)
  );

一些properties配置可能本来就是多级的。 当读取到这样的文件,您可以设置 hierarchical 参数来提醒Vert.x,当操作这个多级属性时,则将配置转换到 Json 对象当中, 这与前述方法设置扁平结构形成了对比。

例如:

server.host=localhost
server.port=8080
multiple.values=1,2,3

获取值:

ConfigStoreOptions propertyWithHierarchical = new ConfigStoreOptions()
  .setFormat("properties")
  .setType("file")
  .setConfig(new JsonObject().put("path", "hierarchical.properties").put("hierarchical", true)
  );
ConfigRetrieverOptions options = new ConfigRetrieverOptions()
  .addStore(propertyWithHierarchical);

ConfigRetriever configRetriever = ConfigRetriever.create(Vertx.vertx(), options);

configRetriever.configStream().handler(config -> {
  String host = config.getJsonObject("server").getString("host");
  Integer port = config.getJsonObject("server").getInteger("port");
  JsonArray multiple = config.getJsonObject("multiple").getJsonArray("values");
  for (int i = 0; i < multiple.size(); i++) {
    Integer value = multiple.getInteger(i);
  }
});

监听配置的变更

Configuration Retriever 定期获取配置信息, 如果获取到的结果与当前不同,那么您可以重新配置应用。 默认情况下配置每5秒重新加载一次。

ConfigRetrieverOptions options = new ConfigRetrieverOptions()
  .setScanPeriod(2000)
  .addStore(store1)
  .addStore(store2);

ConfigRetriever retriever = ConfigRetriever.create(Vertx.vertx(), options);
retriever.getConfig(json -> {
  // 初始化获取配置
});

retriever.listen(change -> {
  // 之前的配置
  JsonObject previous = change.getPreviousConfiguration();
  // 新配置
  JsonObject conf = change.getNewConfiguration();
});

获取上一次的配置

您可以获取上一次获取到的配置而不用 "等到" 被获取的时候。 这需要用如下方式实现:

JsonObject last = retriever.getCachedConfig();

以流的方式读取配置

ConfigRetriever 提供了一个访问配置流的方法。 这是一个 JsonObjectReadStream 。通过注册正确的处理器集合,您 会收到通知:

  • 当获取到一个新的配置

  • 当获取配置时发生错误

  • 当 configuration retriever 关闭(即 endHandler 被调用)

ConfigRetrieverOptions options = new ConfigRetrieverOptions()
  .setScanPeriod(2000)
  .addStore(store1)
  .addStore(store2);

ConfigRetriever retriever = ConfigRetriever.create(Vertx.vertx(), options);
retriever.configStream()
  .endHandler(v -> {
    // retriever 关闭
  })
  .exceptionHandler(t -> {
    // 当获取配置时捕获到错误
  })
  .handler(conf -> {
    // 配置
  });

处理配置

您可以配置一个 processor ,它可以校验并更新配置。 可以通过调用 setConfigurationProcessor 方法来实现。

处理过程绝对不能返回 null 。处理器获取到配置然后返回处理过的配置。 如果处理器不更新配置,它必须将输入的配置返回。 处理器可以抛出异常(例如,校验失败)。

以Future形式获取配置

ConfigRetriever 提供了一个 以 Future 形式接收配置的方式:

Future<JsonObject> future = retriever.getConfig();
future.onComplete(ar -> {
  if (ar.failed()) {
    // 获取配置失败
  } else {
    JsonObject config = ar.result();
  }
});

扩展 Config Retriever

通过实现如下方式,您可以扩展配置:

其他格式

尽管Vert.x对于开箱即用的格式都提供了支持,但是 Vert.x Config 还是提供了额外的格式以供您的应用使用。

Hocon 配置格式

Hocon 配置格式扩展了 Vert.x Configuration Retriever 并提供了对 HOCON 格式 (https://github.com/typesafehub/config/blob/master/HOCON.md)的支持

它支持 json、properties、macros 等格式

使用 Hocon 配置格式

要使用Hocon配置格式, 添加如下依赖:

  • Maven (在您的 pom.xml 文件):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-hocon</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-hocon:4.2.7'

指定配置中心以使用hocon

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 来使用这个格式:

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("file")
  .setFormat("hocon")
  .setConfig(new JsonObject()
    .put("path", "my-config.conf")
  );

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(store));

您必须将 format 设置为 hocon

Yaml 配置格式

Yaml 配置格式扩展了 Vert.x Configuration Retriever 并提供了对 Yaml格式 的支持

使用Yaml配置格式

要使用Yaml配置格式, 添加如下依赖:

  • Maven (在您的 pom.xml 文件):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-yaml</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-yaml:4.2.7'

指定配置中心以使用yaml

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 来使用这个格式:

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("file")
  .setFormat("yaml")
  .setConfig(new JsonObject()
    .put("path", "my-config.yaml")
  );

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(store));

您必须将 format 设置为 yaml

其他配置中心

尽管Vert.x对于开箱即用的配置中心都提供了支持,但是 Vert.x Config 还是提供了额外的格式以供您的应用使用。

Git配置中心

git配置中心是对 Vert.x Configuration Retriever 的扩展, 用于从Git仓库获取配置。

使用git配置中心

要使用Git配置中心, 则添加如下依赖:

  • Maven(在您的 pom.xml 文件):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-git</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle(在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-git:4.2.7'

设置配置中心

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 以使用该配置中心:

ConfigStoreOptions git = new ConfigStoreOptions()
    .setType("git")
    .setConfig(new JsonObject()
        .put("url", "https://github.com/cescoffier/vertx-config-test.git")
        .put("path", "local")
        .put("filesets",
            new JsonArray().add(new JsonObject().put("pattern", "*.json"))));

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(git));

配置需要如下信息:

  • url :git仓库的地址

  • path :仓库被clone的路径(本地目录)

  • user :仓库的git用户名(默认不需要认证)

  • password : git用户的密码

  • idRsaKeyPath :私有仓库所需的 ssh rsa 密钥 uri

  • fileset :指定要读取的文件集合 (与配置中心的目录配置意义相同)

您也可以配置要使用的分支( branch 参数,默认为 master ), 以及远程仓库名( remote 参数,默认为 origin

如何工作

如果本地的仓库目录(由 path 参数指定)不存在,那么配置中心会 clone 远程仓库到这个本地目录。 然后它会读取符合 fileset 配置的文件。

如果本地的仓库目录(由 path 参数指定)存在,它会尝试更新(按需切换分支)。 如果更新失败,则视为获取配置失败。

配置中心会周期性更新 git 仓库来检查配置是否更新。

Kubernetes ConfigMap 配置中心

Kubernetes ConfigMap 配置中心扩展了 Vert.x Configuration Retriever 并提供了 对于 Kubernetes 的 ConfigMap 和 Secrets 的支持。 所以,配置是从 k8s 里的 configMap 或者 secret 对象中读取的。

使用 Kubernetes ConfigMap 配置中心

要使用 Kubernetes ConfigMap 配置中心, 则添加如下依赖:

  • Maven (在您的 pom.xml 文件):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-kubernetes-configmap</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-kubernetes-configmap:4.2.7'

设置配置中心

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 来使用这个配置中心:

ConfigStoreOptions store = new ConfigStoreOptions()
    .setType("configmap")
    .setConfig(new JsonObject()
        .put("namespace", "my-project-namespace")
        .put("name", "configmap-name")
    );

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(store));

您需要设置这个配置中心来找到正确的configMap。这通过如下配置项来解决:

  • namespace - 项目的namespace,默认值为 default 。如果设置了 KUBERNETES_NAMESPACE 环境变量, 则会覆盖其值。

  • name - configMap的名称

  • optional - configMap是否是可选项(默认为 true

如果configMap是由数个元素组成,您可以用 key 参数来告诉 Vert.x 来读取哪一个 key

Vert.x应用必须要有读取configMap的权限。

要从secret中读取数据,只需要将 secret 属性配置为 true

ConfigStoreOptions store = new ConfigStoreOptions()
    .setType("configmap")
    .setConfig(new JsonObject()
        .put("namespace", "my-project-namespace")
        .put("name", "my-secret")
        .put("secret", true)
    );

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(store));

如果configMap访问不到,那么您会得到一个空的JSON object对象作为配置块。 要禁用这个行为并显式声明失败,您需要设置 optionalfalse .

Redis配置中心

Reids配置中心扩展了 Vert.x Configuration Retriever 并提供了从Redis服务获取配置的方法。

使用Redis配置中心

要使用Redis配置中心, 添加如下依赖:

  • Maven (在您的 pom.xml 文件):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-redis</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-redis:4.2.7'

设置配置中心

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 来使用这个配置中心:

ConfigStoreOptions store = new ConfigStoreOptions()
    .setType("redis")
    .setConfig(new JsonObject()
        .put("host", "localhost")
        .put("port", 6379)
        .put("key", "my-configuration")
    );

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(store));

配置中心的配置用于创建 Redis 对象。 更多细节请查阅 Vert.x Redis Client 文档

另外,您可以设置 key 属性来指示配置中心中的某一 field , 默认为 configuration 属性。

Redis客户端使用 HGETALL 配置项来获取配置。

Zookeeper配置中心

Zookeeper配置中心扩展了 Vert.x Configuration Retriever 并提供了从Zookeeper服务获取配置的方法。它使用 Apache Curator 作为客户端

使用zookeeper配置中心

要使用zookeeper配置中心, 添加如下依赖:

  • Maven (在您的 pom.xml ):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-zookeeper</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-zookeeper:4.2.7'

设置配置中心

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 来使用这个配置中心:

ConfigStoreOptions store = new ConfigStoreOptions()
    .setType("zookeeper")
    .setConfig(new JsonObject()
        .put("connection", "localhost:2181")
        .put("path", "/path/to/my/conf")
    );

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(store));

这个配置用来配置 Apache Curator 客户端和包含配置的zookeeper节点的 路径 。 注意:配置的格式可以是JSON等任何Vert.x支持的格式。

这项配置必须需要 connection 属性指定zk服务的连接 字符串 (译者注:英文逗号隔开的多个zk服务节点), 以及 path 属性指定包含配置项的节点(znode)的路径。

您还可以额外配置:

  • maxRetries :重连次数,默认3次。

  • baseSleepTimeBetweenRetries :重试间隔毫秒值,默认1000毫秒。

Consul 配置中心

Consul配置中心扩展了 Vert.x Configuration Retriever , 并提供了从 Consul 获取配置的方法。

使用Consul配置中心

使用Consul配置中心, 需在您的项目构建配置中添加如下 依赖

  • Maven(在您的 pom.xml 文件中):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-consul</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-consul:4.2.7'

设置配置中心

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 以使用该配置中心:

ConfigStoreOptions store = new ConfigStoreOptions()
    .setType("consul")
    .setConfig(new JsonObject()
      .put("host", "localhost")
      .put("port", 8500)
      .put("prefix", "foo")
      .put("raw-data", false)
    );

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(store));

这个配置用来创建 ConsulClient 对象。更多详细信息请查阅Vert.x Consul Client文档。 以下为设置 Consul 配置中心所需的参数:

prefix

构建配置树时需要被忽略的前缀,默认为空。

delimiter

用来分割Consul中的key的分隔符,用以维护配置树中的级别。默认为 "/"。

raw-data

如果 raw-datatrue ,则配置值不会进行类型转换,并且您可以用 config.getString(key) 来获取原始数据,默认为 true

Spring配置中心

Spring配置中心扩展了 Vert.x Configuration Retriever 并提供了从 Spring服务获取配置的方法。

使用Spring配置中心

要使用Spring配置中心, 则添加如下依赖:

  • Maven (在您的 pom.xml 文件):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-spring-config-server</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-spring-config-server:4.2.7'

设置配置中心

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 来使用这个配置中心:

ConfigStoreOptions store = new ConfigStoreOptions()
    .setType("spring-config-server")
    .setConfig(new JsonObject().put("url", "http://localhost:8888/foo/development"));

ConfigRetriever retriever = ConfigRetriever.create(vertx,
    new ConfigRetrieverOptions().addStore(store));

可配置的属性如下:

  • url - 获取配置的 url (强制必填),支持两种格式:

    • /{application}/{environment} ,分别用不同的配置源来生成响应

    • /{application}-{environment}.json ,以具有唯一字段的JSON生成响应,并解析spring占位符

  • timeout - 获取配置超时时间(毫秒),默认3000毫秒。

  • user - 用户(默认无需认证)

  • password - 密码

  • httpClientConfiguration - 底层HTTP客户端的配置

Vault配置中心

Vault配置中心扩展了 Vert.x Configuration Retriever 并提供了从 Vault (https://www.vaultproject.io/) 获取配置的方法。 所以,配置(即secrets)是从Vault获取的。

这个配置中心的 secrets 引擎是 Vault 的 Key/Value version 1 和 version 2 引擎( https://www.vaultproject.io/docs/secrets/kv/index.html )。暂不支持其他secrets引擎。

使用Vault配置中心

要使用Vault配置中心, 添加如下依赖:

  • Maven (在您的 pom.xml 文件):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config-vault</artifactId>
 <version>4.2.7</version>
</dependency>
<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-config</artifactId>
 <version>4.2.7</version>
</dependency>
  • Gradle (在您的 build.gradle 文件):

compile 'io.vertx:vertx-config:4.2.7'
compile 'io.vertx:vertx-config-vault:4.2.7'

指定配置中心

将该库加入classpath或者项目依赖后,您需要配置 ConfigRetriever 来使用这个配置中心:

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("vault")
  .setConfig(config);

ConfigRetriever retriever = ConfigRetriever.create(vertx,
  new ConfigRetrieverOptions().addStore(store));

要使用Vault配置中心,则设置 typevault 。其配置以JSON形式提供。 它配置了对Vault的访问权限、认证信息和secret路径:

JsonObject vault_config = new JsonObject()
  .put("host", "127.0.0.1") // The host name
  .put("port", 8200) // The port
  .put("ssl", true); // 是否使用SSL (默认禁用)

// 认证
PemKeyCertOptions certs = new PemKeyCertOptions()
  .addCertPath("target/vault/config/ssl/client-cert.pem")
  .addKeyPath("target/vault/config/ssl/client-privatekey.pem");
vault_config.put("pemKeyCertOptions", certs.toJson());

// Truststore
JksOptions jks = new JksOptions()
  .setPath("target/vault/config/ssl/truststore.jks");
vault_config.put("trustStoreOptions", jks.toJson());

// 读取secret的路径
vault_config.put("path", "secret/my-secret");

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("vault")
  .setConfig(vault_config);

ConfigRetriever retriever = ConfigRetriever.create(vertx,
  new ConfigRetrieverOptions().addStore(store));}

vault_config 对象可以包含 HTTP client / Web client 的配置, 例如 trust stores、timeout、certificates、port和host。 pathhost 强制必填。 path 指定了需要获取的secret。 host 是Vault服务的hostname。默认情况下使用8200端口。 默认SSL关闭,但是生产环境下您需要开启它。

然后,您需要用如下中的一个方法来配置token或者认证机制。

使用已经存在的token

如果您已经得到了token,则在配置中设置 token 属性:

JsonObject vault_config = new JsonObject();

// ...

//  读取secret的路径
vault_config.put("path", "secret/my-secret");

// The token
vault_config.put("token", token);

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("vault")
  .setConfig(vault_config);

ConfigRetriever retriever = ConfigRetriever.create(vertx,
  new ConfigRetrieverOptions().addStore(store));

您可以使用root token,但是不建议这样做。当token被回收,则对secret的访问也会受阻。 如果token可刷新,则当它过期的时候会被刷新。

生成token

如果您的token本身具有创建token的权限,您可以请求生成token:

JsonObject vault_config = new JsonObject();

// ...

// 读取secret的路径
vault_config.put("path", "secret/my-secret");

// 生成token的配置

// 配置token请求 (https://www.vaultproject.io/docs/auth/token.html)
JsonObject tokenRequest = new JsonObject()
  .put("ttl", "1h")
  .put("noDefault", true)

  // (parts of the tokenRequest object) 用来做生成操作的token(tokenRequest object 的一部分)
  .put("token", token);

vault_config.put("auth-backend", "token") // 指定所用的 auth backend
  .put("renew-window", 5000L) // 更新误差容限(毫秒)
  .put("token-request", tokenRequest); // 传入token生成的配置

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("vault")
  .setConfig(vault_config);

ConfigRetriever retriever = ConfigRetriever.create(vertx,
  new ConfigRetrieverOptions().addStore(store));

当用这种方式,根配置中不必提供token,然后,用于生成token的token嵌于JSON数据被传入。 如果生成的token可刷新,那么在它过期的时候会自动刷新。 renew-window 是更新token有效性的时间窗口。 如果生成的token失效,则访问权限受阻。

使用证书

您可以使用TLS证书作为认证机制。所以,您不需要自己生成token, 它是自动生成的。

JsonObject vault_config = new JsonObject();

// ...

PemKeyCertOptions certs = new PemKeyCertOptions()
  .addCertPath("target/vault/config/ssl/client-cert.pem")
  .addKeyPath("target/vault/config/ssl/client-privatekey.pem");
vault_config.put("pemKeyCertOptions", certs.toJson());

PemTrustOptions trust = new PemTrustOptions()
  .addCertPath("target/vault/config/ssl/cert.pem");
vault_config.put("pemTrustStoreOptions", trust.toJson());

JksOptions jks = new JksOptions()
  .setPath("target/vault/config/ssl/truststore.jks");
vault_config.put("trustStoreOptions", jks.toJson());

vault_config.put("auth-backend", "cert");

// 读取secret的路径
vault_config.put("path", "secret/my-secret");

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("vault")
  .setConfig(vault_config);

ConfigRetriever retriever = ConfigRetriever.create(vertx,
  new ConfigRetrieverOptions().addStore(store));

查看HTTP客户端和Web客户端的配置来传输证书。如果生成的token可刷新, 那么token会被刷新;如果不是,则配置中心会再次尝试认证。

使用 AppRole

当您的应用被Vault所知悉且您已经持有 appRoleIdsecretId , 此时会用到 AppRole 。 您不需要自己生成token,这个token会自动生成:

JsonObject vault_config = new JsonObject();

// ...

vault_config
  .put("auth-backend", "approle") // Set the auth-backend to approle
  .put("approle", new JsonObject()  // Configure the role id and secret it
    .put("role-id", appRoleId).put("secret-id", secretId)
  );

// 读取secret的路径
vault_config.put("path", "secret/my-secret");

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("vault")
  .setConfig(vault_config);

ConfigRetriever retriever = ConfigRetriever.create(vertx,
  new ConfigRetrieverOptions().addStore(store));

如果生成的token可刷新,那么他会被刷新;否则配置中心会再次尝试认证。

使用 username 和 password

user/app 在使用 username/password做认证的时候,会以 userpass 作为验证后台。 您并不需要自己生成token,因为认证过程中token已经生成:

JsonObject vault_config = new JsonObject();

// ...

vault_config
  .put("auth-backend", "userpass") // 使用 userpass 作为验证后端
  .put("user-credentials", new JsonObject()
    .put("username", username).put("password", password)
  );

// 读取secrete路径
vault_config.put("path", "secret/my-secret");

ConfigStoreOptions store = new ConfigStoreOptions()
  .setType("vault")
  .setConfig(vault_config);

ConfigRetriever retriever = ConfigRetriever.create(vertx,
  new ConfigRetrieverOptions().addStore(store));

如果生成的token可刷新,那么他会被刷新;否则配置中心会再次尝试认证。