嗯…Spring虽好但用多会厌。有没有性能更好的平替方案呢?有,Vert.x。于是重新出发学习Vert.x,学了之后发现其实还可以自己做一些封装,于是在Vert.x的基础上弄了一个名为vtx_fw的基础框架。不过框架尚未稳定暂时就不对外公开了,但是有些坑还是可以跟各位同好们分享一下的。
因此,我又挖坑了。开了一个Vert.x系列,希望通过自己填坑经验帮助到其他有需要的人。
首发第一篇讲的是ConfigRetriever无法获取配置信息。受Springboot影响vtx_fw项目结构也与springboot的类似,也是通过读取yaml文件获取配置信息,其中version1的Yaml配置获取将采用以下代码处理:
ConfigStoreOptions configStore = new ConfigStoreOptions();
configStore.setType(CONFIG_TYPE);
// 指定配置文件路径
JsonObject pathJson = new JsonObject();
pathJson.put(CONFIG_PARAM_PATH, CONFIG_DIRECTORY);
// 读取配置文件通配符
JsonArray patternArr = new JsonArray();
patternArr.add(new JsonObject().put(CONFIG_PARAM_PATTERNS, CONFIG_FORMAT_YAML + "/*.yaml")
.put(CONFIG_PARAM_FORMAT, CONFIG_FORMAT_YAML));
pathJson.put(CONFIG_PARAM_FILESET, patternArr);
configStore.setConfig(pathJson);
// 配置获取所有yml文件数据
ConfigRetriever retriever = ConfigRetriever.create(vertx, new ConfigRetrieverOptions().addStore(configStore));
// 获取配置信息
retriever.getConfig(conf -> {
if (conf.succeeded()) {
System.out.println("YamlConfig.start5:" + conf.result());
YamlConstants.CONF_JSON = conf.result();
} else {
LOGGER.error("func[YamlConfig.start] Exception [{} - {}]",
new Object[] {conf.cause(), conf.cause().getMessage()});
}
});
在IDE工具中执行是没有问题的,能够正常获取某目录下的所有文件并可根据通配符“*”可以全部获取,如下所示:
{
"databases": {
"has-open": true,
"db-type": "mysql",
"nodes": [{
"name": "test_write",
"uri": "jdbc:mysql://127.0.0.1:3506/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8",
"driver-class-name": "com.mysql.cj.jdbc.Driver",
"username": "yzh",
"password": "0624"
}, {
"name": "test_read",
"uri": "jdbc:mysql://127.0.0.1:3506/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8",
"driver-class-name": "com.mysql.cj.jdbc.Driver",
"username": "yzh",
"password": "0624"
}],
"hikari": {
"pool-name": "vtx-hikari-pool",
"minimum-idle": 100,
"maximum-pool-size": 500,
"idle-timeout": 18000
},
"retry": {
"get-counter": 10,
"interval": 500
}
},
"zookeeper": {
"zookeeper-hosts": "172.20.0.2:2181,172.20.0.3:2181,172.20.0.4:2181",
"root-path": "io.kida.yuen",
"retry": {
"initial-sleep-time": 100,
"max-times": 2
},
"has-open": false
},
"server": {
"name": "vtx_biz",
"active": "dev",
"port": 8197,
"context": "biz",
"timeout": 120,
"http": {
"header": ["x-requested-with", "Access-Control-Allow-Origin", "origin", "Content-Type", "accept"]
},
"event-bus": {
"timeout": 10000
}
},
"thread": {
"deploy": {
"init": 1,
"max-size": 128,
"pool-name": "vtx-thread-pool"
},
"worker": 64,
"init-pool-size": 32,
"eventloop-pool-size": 64
}
}
但是在打包成fat jar后目录路径发生变化获取数据为空,并因为YamlProcess没有包含在/META/service目录中,因此报以下错误:
2022-05-12 16:02:03,760:DEBUG main (BootstrapConfig.java:77) - In order to get the startup configuration first initialize the YamlConfig class...
log4j:WARN No appenders could be found for logger (io.vertx.core.logging.LoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2022-05-12 16:02:04,085:ERROR vert.x-eventloop-thread-1 (BootstrapConfig.java:107) - func[BootstrapConfig.setupAndDeploy] Main method error Exception [java.lang.IllegalArgumentException: Unknown configuration format `yaml`, supported types are [json, raw, properties] - java.lang.IllegalArgumentException: Unknown configuration format `yaml`, supported types are [json, raw, properties]]
通过在网上搜索,最终在StackOverflow中找到了解决方案
按上图所述,遇到这种报错需要在maven-shade-plugin
中添加配置,如下图所示:
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
加上配置后经验证还是未解决无法获取配置信息的问题。后来经过多次试验后得知“path”参数后面对应的应该是绝对路径,因此如果你的配置是外部配置,可以通过ConfigRetriever来获取。但如果需要读取fat jar中的配置文件,还是乖乖地用fileSystem来获取,如下图:
Buffer bootBfr = vertx.fileSystem().readFileBlocking(BOOTSTRAP_PATH);
try {
Map<String, Object> reMap = new HashMap<>();
if (null != bootBfr) {
Map<?, ?> baseMap = (Map<?, ?>)new Yaml().load(bootBfr.toString());
Map<String, Object> bootMap = baseMap.entrySet().stream()
.collect(Collectors.toMap(entry -> String.valueOf(entry.getKey()), entry -> entry.getValue()));
reMap.putAll(bootMap);
String envStr = new JsonObject(bootMap).getJsonObject("server").getString("active");
vertx.fileSystem().readDir(CONFIG_FOLDER + "/" + envStr, dirHeader -> {
if (dirHeader.succeeded()) {
List<String> fileList = dirHeader.result();
if (null != fileList && !fileList.isEmpty()) {
for (String pathName : fileList) {
Buffer pluginBfr = vertx.fileSystem().readFileBlocking(pathName);
if (null != pluginBfr) {
Map<?, ?> pluginMap = (Map<?, ?>)new Yaml().load(pluginBfr.toString());
Map<String, Object> appMap = pluginMap.entrySet().stream().collect(Collectors
.toMap(entry -> String.valueOf(entry.getKey()), entry -> entry.getValue()));
reMap.putAll(appMap);
}
}
}
}
YamlConstants.CONF_JSON = new JsonObject(reMap);
});
}
} catch (Exception e) {
LOGGER.error("func[YamlConfig.start] Exception [{} - {}]", new Object[] {e.getCause(), e.getMessage()});
}
对应上述的代码,目录结构也要做相应的调整,如下图所示:
它会先获取configs下的bootstrap.yml文件,读取里面的server.active参数,通过参数内容找到对应目录下的文件地址,并通过fileSystem获取所有文件。