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:
  1. <dependency>
  2. <groupId>io.vertx</groupId>
  3. <artifactId>vertx-config</artifactId>
  4. <version>4.1.5</version>
  5. </dependency>
  • Gradle:
  1. compile 'io.vertx:vertx-config:4.1.5'

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

  1. ConfigRetriever retriever = ConfigRetriever.create(vertx);

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

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

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

  1. ConfigStoreOptions httpStore = new ConfigStoreOptions()
  2. .setType("http")
  3. .setConfig(new JsonObject()
  4. .put("host", "localhost").put("port", 8080).put("path", "/conf"));
  5. ConfigStoreOptions fileStore = new ConfigStoreOptions()
  6. .setType("file")
  7. .setConfig(new JsonObject().put("path", "my-config.json"));
  8. ConfigStoreOptions sysPropsStore = new ConfigStoreOptions().setType("sys");
  9. ConfigRetrieverOptions options = new ConfigRetrieverOptions()
  10. .addStore(httpStore).addStore(fileStore).addStore(sysPropsStore);
  11. ConfigRetriever retriever = ConfigRetriever.create(vertx, options);

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

  1. ConfigStoreOptions fileStore = new ConfigStoreOptions()
  2. .setType("file")
  3. .setOptional(true)
  4. .setConfig(new JsonObject().put("path", "my-config.json"));
  5. ConfigStoreOptions sysPropsStore = new ConfigStoreOptions().setType("sys");
  6. ConfigRetrieverOptions options = new ConfigRetrieverOptions().addStore(fileStore).addStore(sysPropsStore);
  7. ConfigRetriever retriever = ConfigRetriever.create(vertx, options);

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

  1. retriever.getConfig(ar -> {
  2. if (ar.failed()) {
  3. // 获取配置失败
  4. } else {
  5. JsonObject config = ar.result();
  6. }
  7. });

覆盖规则

配置中心的声明顺序非常重要, 因为它定义了覆盖顺序。对于冲突的key, 声明的配置中心会覆盖之前的。

使用配置

获取到的配置可用于:

  • 配置verticles,
  • 配置端口,客户端,location等等,
  • 配置Vert.x自身

配置一个单独的Verticle

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

  1. ConfigRetriever retriever = ConfigRetriever.create(vertx);
  2. retriever.getConfig(json -> {
  3. JsonObject result = json.result();
  4. vertx.createHttpServer()
  5. .requestHandler(req -> result.getString("message"))
  6. .listen(result.getInteger("port"));
  7. });

配置一组Verticles

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

  1. ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions()
  2. .addStore(new ConfigStoreOptions().setType("file").setConfig(new JsonObject().put("path", "verticles.json"))));
  3. retriever.getConfig(json -> {
  4. JsonObject a = json.result().getJsonObject("a");
  5. JsonObject b = json.result().getJsonObject("b");
  6. vertx.deployVerticle(GreetingVerticle.class.getName(), new DeploymentOptions().setConfig(a));
  7. vertx.deployVerticle(GreetingVerticle.class.getName(), new DeploymentOptions().setConfig(b));
  8. });

配置Vert.x自身

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

  1. Vertx vertx = Vertx.vertx();
  2. // 创建 config retriever
  3. ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions()
  4. .addStore(new ConfigStoreOptions().setType("file").setConfig(new JsonObject().put("path", "vertx.json"))));
  5. // 获取配置
  6. retriever.getConfig(json -> {
  7. JsonObject result = json.result();
  8. // 关闭vertx对象,我们再也用不到它了
  9. vertx.close();
  10. // 用获取到的配置创建一个新的Vert.x实例
  11. VertxOptions options = new VertxOptions(result);
  12. Vertx newVertx = Vertx.vertx(options);
  13. // 部署您的Verticle
  14. newVertx.deployVerticle(GreetingVerticle.class.getName(), new DeploymentOptions().setConfig(result.getJsonObject("a")));
  15. });

向事件总线传播配置变更

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

  1. ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions()
  2. .addStore(new ConfigStoreOptions().setType("file").setConfig(new JsonObject().put("path", "verticles.json"))));
  3. retriever.getConfig(json -> {
  4. //...
  5. });
  6. retriever.listen(change -> {
  7. JsonObject json = change.getNewConfiguration();
  8. vertx.eventBus().publish("new-configuration", json);
  9. });

配置的结构

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

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

文件

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

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

path 配置项是必填项。

JSON

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

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

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

环境变量

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

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

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

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

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

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

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

系统参数

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

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

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

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

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

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

例子:

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

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

  1. {
  2. "server": {
  3. "host": "localhost",
  4. "port": 8080
  5. }
  6. }

HTTP

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

  1. ConfigStoreOptions http = new ConfigStoreOptions()
  2. .setType("http")
  3. .setConfig(new JsonObject()
  4. .put("host", "localhost")
  5. .put("port", 8080)
  6. .put("path", "/A"));

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

  1. ConfigStoreOptions http = new ConfigStoreOptions()
  2. .setType("http")
  3. .setConfig(new JsonObject()
  4. .put("host", "localhost")
  5. .put("port", 8080)
  6. .put("ssl", true)
  7. .put("path", "/A")
  8. .put("headers", new JsonObject().put("Accept", "application/json")));

事件总线

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

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

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

目录

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

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

  • 一个 path - 读取文件的根目录
  • 至少一个 fileset - 一个用于选择文件的对象
  • 对于properties文件,您可以用 raw-data 属性来禁止类型转换。

每一个 fileset 都包含:

  • 一个 pattern :一个Ant风格的pattern用于选择文件。 这个pattern应用于相对当前工作目录的相对路径。
  • 一个可选的 format ,它制定了文件的格式(每一个fileset可以用一个不同的format, 但是同一个fileset共用一个format)
  1. ConfigStoreOptions dir = new ConfigStoreOptions()
  2. .setType("directory")
  3. .setConfig(new JsonObject().put("path", "config")
  4. .put("filesets", new JsonArray()
  5. .add(new JsonObject().put("pattern", "dir/*json"))
  6. .add(new JsonObject().put("pattern", "dir/*.properties")
  7. .put("format", "properties"))
  8. ));
  9. ConfigStoreOptions dirWithRawData = new ConfigStoreOptions()
  10. .setType("directory")
  11. .setConfig(new JsonObject().put("path", "config")
  12. .put("filesets", new JsonArray()
  13. .add(new JsonObject().put("pattern", "dir/*json"))
  14. .add(new JsonObject().put("pattern", "dir/*.properties")
  15. .put("format", "properties").put("raw-data", true))
  16. ));

Properties 文件和原始数据

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

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

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

例如:

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

获取值:

  1. ConfigStoreOptions propertyWithHierarchical = new ConfigStoreOptions()
  2. .setFormat("properties")
  3. .setType("file")
  4. .setConfig(new JsonObject().put("path", "hierarchical.properties").put("hierarchical", true)
  5. );
  6. ConfigRetrieverOptions options = new ConfigRetrieverOptions()
  7. .addStore(propertyWithHierarchical);
  8. ConfigRetriever configRetriever = ConfigRetriever.create(Vertx.vertx(), options);
  9. configRetriever.configStream().handler(config -> {
  10. String host = config.getJsonObject("server").getString("host");
  11. Integer port = config.getJsonObject("server").getInteger("port");
  12. JsonArray multiple = config.getJsonObject("multiple").getJsonArray("values");
  13. for (int i = 0; i < multiple.size(); i++) {
  14. Integer value = multiple.getInteger(i);
  15. }
  16. });

监听配置的变更

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

  1. ConfigRetrieverOptions options = new ConfigRetrieverOptions()
  2. .setScanPeriod(2000)
  3. .addStore(store1)
  4. .addStore(store2);
  5. ConfigRetriever retriever = ConfigRetriever.create(Vertx.vertx(), options);
  6. retriever.getConfig(json -> {
  7. // 初始化获取配置
  8. });
  9. retriever.listen(change -> {
  10. // 之前的配置
  11. JsonObject previous = change.getPreviousConfiguration();
  12. // 新配置
  13. JsonObject conf = change.getNewConfiguration();
  14. });

获取上一次的配置

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

  1. JsonObject last = retriever.getCachedConfig();

以流的方式读取配置

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

  • 当获取到一个新的配置
  • 当获取配置时发生错误
  • 当 configuration retriever 关闭(即 endHandler 被调用)
  1. ConfigRetrieverOptions options = new ConfigRetrieverOptions()
  2. .setScanPeriod(2000)
  3. .addStore(store1)
  4. .addStore(store2);
  5. ConfigRetriever retriever = ConfigRetriever.create(Vertx.vertx(), options);
  6. retriever.configStream()
  7. .endHandler(v -> {
  8. // retriever 关闭
  9. })
  10. .exceptionHandler(t -> {
  11. // 当获取配置时捕获到错误
  12. })
  13. .handler(conf -> {
  14. // 配置
  15. });

处理配置

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

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

扩展 Config Retriever

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

  • ConfigProcessor SPI 来增加对新格式的支持
  • ConfigStoreFactory SPI来增加配置中心的支持(获取配置数据的位置)

其他格式

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

Yaml 配置格式

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

使用Yaml配置格式

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

  • Maven:
  1. <dependency>
  2. <groupId>io.vertx</groupId>
  3. <artifactId>vertx-config-yaml</artifactId>
  4. <version>4.1.5</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>io.vertx</groupId>
  8. <artifactId>vertx-config</artifactId>
  9. <version>4.1.5</version>
  10. </dependency>
  • Gradle:
  1. compile 'io.vertx:vertx-config:4.2.0'
  2. compile 'io.vertx:vertx-config-yaml:4.2.0'

指定配置中心以使用yaml

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

  1. ConfigStoreOptions store = new ConfigStoreOptions()
  2. .setType("file")
  3. .setFormat("yaml")
  4. .setConfig(new JsonObject()
  5. .put("path", "my-config.yaml")
  6. );
  7. ConfigRetriever retriever = ConfigRetriever.create(vertx,
  8. new ConfigRetrieverOptions().addStore(store));

您必须将 format 设置为 yaml

其他配置中心

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

Git配置中心

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

使用git配置中心

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

  • Maven:
  1. <dependency>
  2. <groupId>io.vertx</groupId>
  3. <artifactId>vertx-config-git</artifactId>
  4. <version>4.1.5</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>io.vertx</groupId>
  8. <artifactId>vertx-config</artifactId>
  9. <version>4.1.5</version>
  10. </dependency>
  • Gradle:
  1. compile 'io.vertx:vertx-config:4.1.5'
  2. compile 'io.vertx:vertx-config-git:4.1.5'

设置配置中心

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

  1. ConfigStoreOptions git = new ConfigStoreOptions()
  2. .setType("git")
  3. .setConfig(new JsonObject()
  4. .put("url", "https://github.com/cescoffier/vertx-config-test.git")
  5. .put("path", "local")
  6. .put("filesets",
  7. new JsonArray().add(new JsonObject().put("pattern", "*.json"))));
  8. ConfigRetriever retriever = ConfigRetriever.create(vertx,
  9. 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 仓库来检查配置是否更新。

Redis配置中心

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

使用Redis配置中心

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

  • Maven:
  1. <dependency>
  2. <groupId>io.vertx</groupId>
  3. <artifactId>vertx-config-redis</artifactId>
  4. <version>4.1.5</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>io.vertx</groupId>
  8. <artifactId>vertx-config</artifactId>
  9. <version>4.1.5</version>
  10. </dependency>
  • Gradle:
  1. compile 'io.vertx:vertx-config:4.1.5'
  2. compile 'io.vertx:vertx-config-redis:4.1.5'

设置配置中心

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

  1. ConfigStoreOptions store = new ConfigStoreOptions()
  2. .setType("redis")
  3. .setConfig(new JsonObject()
  4. .put("host", "localhost")
  5. .put("port", 6379)
  6. .put("key", "my-configuration")
  7. );
  8. ConfigRetriever retriever = ConfigRetriever.create(vertx,
  9. new ConfigRetrieverOptions().addStore(store));

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

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

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