微服务架构
你当前正在浏览历史版本 Vert.x 5.1.10 的文档。 访问本页面的 最新版本。

Vert.x 配置中心(Config)

Vert.x Config 提供了配置 Vert.x 应用程序的途径。 它:

  • 支持多种配置语法(JSON、Properties、YAML(扩展)、HOCON(扩展)等)

  • 支持多种配置存储,如文件、目录、HTTP、Git(扩展)、Redis(扩展)、系统属性以及环境变量

  • 允许你定义处理顺序和覆盖规则

  • 支持运行时动态重新配置

核心概念

该库主要围绕以下概念构建:

Config Retriever(配置检索器) 由 Vert.x 应用程序实例化并使用。它配置了一组配置存储(Configuration Store)。 Configuration Store(配置存储) 定义了读取配置数据的位置以及格式(默认为 JSON)。

配置最终作为 JSON 对象获取。

使用 Config Retriever

要使用 Config Retriever,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

添加依赖后,你首先需要实例化 ConfigRetriever:

ConfigRetriever retriever = ConfigRetriever.create(vertx);

默认情况下,Config Retriever 配置了以下存储(按此顺序):

  • Vert.x Verticle 的 config()

  • 系统属性(System Properties)

  • 环境变量(Environment Variables)

  • 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().onComplete(ar -> {
  if (ar.failed()) {
    // 获取配置失败
  } else {
    JsonObject config = ar.result();
  }
});

覆盖规则

配置存储的声明顺序非常重要,因为它定义了覆盖关系。对于冲突的键,最后声明的配置存储会覆盖先前配置存储提供的值。举个例子,我们有两个配置存储:

  • 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}。

使用获取到的配置

获取到的配置可用于:

  • 配置 Verticle

  • 配置端口、客户端、地址等

  • 配置 Vert.x 自身

本节给出一些使用示例。

配置单个 Verticle

以下示例可以放置在 Verticle 的 start 方法中。它检索配置(使用默认存储),并使用配置内容来配置 HTTP 服务端。

ConfigRetriever retriever = ConfigRetriever.create(vertx);
return retriever
  .getConfig()
  .compose(json -> vertx.createHttpServer()
    .requestHandler(req -> req.response().end(json.getString("message")))
    .listen(json.getInteger("port"))
  );

配置一组 Verticle

以下示例使用 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().onComplete(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();
// 创建配置检索器
ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions()
  .addStore(new ConfigStoreOptions().setType("file").setConfig(new JsonObject().put("path", "vertx.json"))));

// 检索配置
retriever.getConfig().onComplete(json -> {
  JsonObject result = json.result();
  // 关闭临时 Vert.x 实例,我们不再需要它。
  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")));
});

将配置变更传播到 Event Bus

Vert.x Config 会在配置发生变更时通知你。如果你希望响应此事件,需要自行实现响应逻辑。例如,你可以取消部署并重新部署 Verticle,或者在 Event Bus 上发送新配置。以下示例展示了后一种情况:它在 Event Bus 上广播新配置,感兴趣的 Verticle 可以监听此地址并自行更新:

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

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

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

支持的配置存储(Configuration Store)

Config Retriever 提供了多种开箱即用的配置存储和格式。 更多配置存储和格式以扩展的形式提供,你也可以实现自己的存储。

配置结构

每个声明的数据存储都必须指定 type。它也可以定义 format;如果未指定,默认使用 JSON。

某些配置存储需要额外的配置(例如文件路径等)。该配置通过 setConfig 以 JSON 对象的形式传入。

文件(File)

此配置存储直接从文件中读取配置。它支持所有支持的格式。

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。

环境变量(Environment Variables)

此配置存储将环境变量转换为 JSON 对象,并合并到全局配置中。

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-data 为 true,则不会尝试转换值,你可以使用 config.getString(key) 获取原始值。这在处理大整数时非常有用。

如果你想指定导入的键集合,可以使用 keys 属性。它会过滤掉所有未选中的键。键必须逐个列出:

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

系统属性(System Properties)

此配置存储将系统属性转换为 JSON 对象,并合并到全局配置中。

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

此配置存储不支持 format 配置。

你可以配置 cache 属性(默认为 true),它决定了是否在首次访问时缓存系统属性并且不再重新加载它们。

你也可以配置 raw-data 属性(默认为 false)。如果 raw-data 为 true,则不会尝试转换值,你可以使用 config.getString(key) 获取原始值。这在处理大整数时非常有用。

此外,还有 hierarchical 属性(默认为 false)。如果 hierarchical 为 true,系统属性将被解析为嵌套的 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、port 和 path 属性来配置主机、端口和路径。你还可以通过 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")));

Event Bus

此 Event Bus 配置存储从 Event Bus 接收配置。该存储允许你在本地和分布式组件之间分发配置。

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

此配置存储支持任意格式。

目录(Directory)

此配置存储与 file 配置存储类似,但它不是读取单个文件,而是从目录中读取多个文件。

此配置存储的配置需要:

  • path - 文件所在的根目录

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

  • 对于 Properties 文件,你可以使用 raw-data 属性指示是否要禁用类型转换

每个 fileset 包含:

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

  • 可选的 format,用于指示文件的格式(每个 fileset 可以使用不同的格式,但是同一个 fileset 中的文件必须具有相同的格式)。

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);
  }
});

监听配置变更

Config Retriever 会定期获取配置,如果获取的结果与当前配置不同,你的应用程序可以重新进行配置。默认情况下,配置每 5 秒重新加载一次。

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

ConfigRetriever retriever = ConfigRetriever.create(Vertx.vertx(), options);
retriever.getConfig().onComplete(json -> {
  // 初次检索配置
});

retriever.listen(change -> {
  // 上一次配置
  JsonObject previous = change.getPreviousConfiguration();
  // 新配置
  JsonObject conf = change.getNewConfiguration();
});

获取上一次检索的配置

你可以无需“等待”检索即可获取上一次检索到的配置,方法如下:

JsonObject last = retriever.getCachedConfig();

以流(Stream)的形式读取配置

ConfigRetriever 提供了访问配置流的途径。 它是一个以 JsonObject 为数据项的 ReadStream。通过注册相应的处理器,你可以在以下时机收到通知:

  • 检索到新配置时

  • 检索配置发生错误时

  • 配置检索器关闭时(调用 endHandler)

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

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

处理配置(Processing Configuration)

你可以配置一个处理器(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 Config 还提供了可在应用程序中使用的扩展格式。

HOCON 配置格式(Configuration Format)

HOCON 配置格式对 Vert.x Configuration Retriever 进行了扩展,提供了对 HOCON 格式的支持。

它支持 include 包含、JSON、Properties 以及宏等特性。

使用 HOCON 配置格式

要使用 HOCON 配置格式,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置存储以使用 HOCON

将其添加到类路径或依赖后,你需要配置 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 即可。

使用系统环境变量覆盖配置

HOCON 支持通过带有 CONFIG_FORCE_ 前缀的键来实现 系统环境变量覆盖。你可以在配置中将 hocon.env.override 指定为 true 来启用此特性:

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

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

YAML 配置格式(Configuration Format)

YAML 配置格式对 Vert.x Configuration Retriever 进行了扩展,提供了对 YAML 配置格式的支持。

使用 YAML 配置格式

要使用 YAML 配置格式,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置存储以使用 YAML

将其添加到类路径或依赖后,你需要配置 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 Config 还提供了可在应用程序中使用的扩展存储。

Git 配置存储(Configuration Store)

Git 配置存储是 Vert.x Configuration Retriever 的一个扩展,用于从 Git 仓库中获取配置。

使用 Git 配置存储

要使用 Git 配置存储,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置该存储

将其添加到类路径或依赖后,你需要配置 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

  • 仓库克隆的 path(本地目录)

  • 用于私有仓库的 user(默认无认证)

  • 用户的 password

  • 用于私有仓库且需要 SSH URI 时的 idRsaKeyPath

  • 至少一个指示要读取的文件集的 fileset(其行为与目录配置存储相同)。

你还可以配置要使用的 branch(默认为 master)以及 remote 远程仓库名称(默认为 origin)。

工作原理

若本地 path 不存在,配置存储会将仓库克隆到该目录中。然后读取匹配不同文件集的文件。

若本地 path 已存在,它会尝试更新该目录(必要时会切换分支)。如果更新失败,则配置获取失败。

配置存储会定期更新仓库,以检查配置是否有更新。

Kubernetes ConfigMap 存储

Kubernetes ConfigMap 存储对 Vert.x Configuration Retriever 进行了扩展,提供了对 Kubernetes ConfigMap 和 Secret 的支持。因此,可以通过读取 ConfigMap 或 Secret 来获取配置。

使用 Kubernetes ConfigMap 存储

要使用 Kubernetes ConfigMap 存储,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置该存储

将其添加到类路径或依赖后,你需要配置 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 - 项目命名空间,默认为 default。如果设置了 KUBERNETES_NAMESPACE 环境变量,则会优先使用该值。

  • name - ConfigMap 的名称

  • optional - 该 ConfigMap 是否是可选的(默认为 true)

如果 ConfigMap 由多个元素组成,你可以使用 key 参数指定要读取哪一个 key。

应用程序必须具备读取该 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 对象作为配置块。若要禁用此默认行为并使其显式失败,可以将 optional 配置设置为 false。

Redis 配置存储(Configuration Store)

Redis 配置存储对 Vert.x Configuration Retriever 进行了扩展,提供了从 Redis 服务器检索配置的方法。

使用 Redis 配置存储

要使用 Redis 配置存储,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置该存储

将其添加到类路径或依赖后,你需要配置 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,指示该存储将配置保存在哪个键/字段中。默认使用 configuration。

创建的 Redis 客户端使用 HGETALL 命令来获取配置。

ZooKeeper 配置存储(Configuration Store)

ZooKeeper 配置存储对 Vert.x Configuration Retriever 进行了扩展,提供了从 ZooKeeper 服务器检索配置的方法。它使用 Apache Curator 作为客户端。

使用 ZooKeeper 配置存储

要使用 ZooKeeper 配置存储,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置该存储

将其添加到类路径或依赖后,你需要配置 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 节点 path。请注意,配置格式可以是 JSON,也可以是任何受支持的格式。

该配置需要提供指示 ZooKeeper 服务器连接字符串的 connection 属性,以及指示包含该配置的节点路径的 path 属性。

此外,你还可以配置:

  • maxRetries:连接尝试次数,默认为 3

  • baseSleepTimeBetweenRetries:重试之间的等待毫秒数(指数退避策略),默认为 1000 毫秒。

Consul 配置存储(Configuration Store)

Consul 配置存储对 Vert.x Configuration Retriever 进行了扩展,提供了从 Consul 获取配置的能力。

使用 Consul 配置存储

要使用 Consul 配置存储,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置该存储

将其添加到类路径或依赖后,你需要配置 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 存储中的键以生成配置树层级结构的符号。默认为 "/"。

raw-data

若 raw-data 为 true,则不会尝试转换值,你可以使用 config.getString(key) 获取原始值。默认为 true。

Spring Config Server 存储

Spring Config Server 存储对 Vert.x Configuration Retriever 进行了扩展,提供了从 Spring Server 检索配置的方法。

使用 Spring Config Server 存储

要使用 Spring Config Server 存储,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置该存储

将其添加到类路径或依赖后,你需要配置 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}:返回包含独立 propertySources 的响应

    • /{application}-{environment}.json:以 JSON 格式返回响应,包含唯一定义的字段并已解析 Spring 占位符

  • timeout - 检索配置的超时时间(毫秒),默认为 3000

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

  • password - 密码 password

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

Vault 配置存储(Config Store)

Vault 存储对 Vert.x Configuration Retriever 进行了扩展,提供了对 Vault (https://www.vaultproject.io/) 的支持。 因此,可以从 Vault 中检索配置(Secret)。

该存储支持的机密引擎为 Vault 键/值(Key/Value)版本 1 和版本 2 引擎(https://www.vaultproject.io/docs/secrets/kv/index.html)。不支持其他机密引擎。

使用 Vault 配置存储

要使用 Vault 配置存储,请将以下依赖添加到构建描述文件的 dependencies 节点中:

  • Maven(在你的 pom.xml 中):

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

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

配置该存储

将其添加到类路径或依赖后,你需要配置 ConfigRetriever 以使用该存储:

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

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

要使用 Vault 配置存储,请将 type 设置为 vault。配置以 JSON 形式提供,用于配置对 Vault 的访问、认证方式以及要检索的 secret 路径:

JsonObject vault_config = new JsonObject()
  .put("host", "127.0.0.1") // 主机名
  .put("port", 8200) // 端口
  .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());

// 信任库
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 客户端 / Web 客户端配置,例如信任库、超时、证书、端口和主机。path 和 host 项为必填项。path 指示要检索的 secret。host 为 Vault 服务器的主机名。默认端口为 8200。默认禁用 SSL,但在生产环境中建议启用它。

接下来,你需要使用以下方法之一来配置所使用的 Token 或认证机制。

使用现有 Token

如果你已知所使用的 Token,请在配置中设置 token 项:

JsonObject vault_config = new JsonObject();

// ...

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

// 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)

  // 用于请求生成的 Token(tokenRequest 对象的一部分)
  .put("token", token);

vault_config.put("auth-backend", "token") // 指示使用的认证后端
  .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 需在嵌套的 JSON 结构中传递。如果生成的 Token 是可续期的,它将在到期时自动续期。renew-window 是添加到 Token 有效期中用于提前续期的时间窗口。如果生成的 Token 被吊销,对该 secret 的访问将被阻止。

使用证书

你可以使用 TLS 证书作为认证机制。这样你无需预先知晓 Token,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 是可续期的,它将被自动续期。如果不可续期,该存储将尝试重新认证。

使用 AppRole

当你的应用程序已被 Vault 登记并且你拥有 appRoleId 和 secretId 时,可以使用 AppRole。你无需手动提供 Token,Token 会自动生成:

JsonObject vault_config = new JsonObject();

// ...

vault_config
  .put("auth-backend", "approle") // 将 auth-backend 设置为 approle
  .put("approle", new JsonObject()  // 配置 role id 和 secret id
    .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 是可续期的,它将被自动续期。如果不可续期,该存储将尝试重新认证。

使用用户名和密码

当用户或应用程序使用用户名/密码进行认证时,可使用 userpass 认证后端。你无需预先提供 Token,因为在认证过程中会自动生成 Token:

JsonObject vault_config = new JsonObject();

// ...

vault_config
  .put("auth-backend", "userpass") // 将 auth-backend 设置为 userpass
  .put("user-credentials", new JsonObject()
    .put("username", username).put("password", password)
  );

// 要读取的 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 是可续期的,它将被自动续期。如果不可续期,该存储将尝试重新认证。