From 89dbafe5c563b4bc85afa9f67a6ea9e515a776d1 Mon Sep 17 00:00:00 2001 From: Lijx Date: Thu, 24 Nov 2022 20:05:23 +0800 Subject: [PATCH] Support for Consul Configuration Center to dynamically adjust parameters (#1007) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Support for Consul Configuration Center to dynamically adjust parameters * Optimize(Support for Consul Configuration Center to dynamically adjust parameters ) * Second optimization(Support for Consul Configuration Center to dynamically adjust parameters ) * delete empty rows --- .../pom.xml | 45 ++++++++++ .../ConfigConsulExampleApplication.java | 31 +++++++ .../src/main/resources/bootstrap.yml | 18 ++++ hippo4j-example/pom.xml | 1 + .../pom.xml | 7 ++ .../config/ConfigHandlerConfiguration.java | 13 +++ .../refresher/ConsulRefresherHandler.java | 86 +++++++++++++++++++ pom.xml | 1 + 8 files changed, 202 insertions(+) create mode 100644 hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/pom.xml create mode 100644 hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/src/main/java/cn/hippo4j/example/config/consul/ConfigConsulExampleApplication.java create mode 100644 hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/src/main/resources/bootstrap.yml create mode 100644 hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/ConsulRefresherHandler.java diff --git a/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/pom.xml b/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/pom.xml new file mode 100644 index 00000000..e2e5d937 --- /dev/null +++ b/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + cn.hippo4j + hippo4j-example + ${revision} + + hippo4j-config-consul-spring-boot-starter-example + + + true + + + + + org.springframework.boot + spring-boot-starter-web + + + cn.hippo4j + hippo4j-example-core + ${revision} + + + cn.hippo4j + hippo4j-config-spring-boot-starter + ${revision} + + + org.springframework.cloud + spring-cloud-starter-consul-config + ${consul.version} + + + io.micrometer + micrometer-registry-prometheus + + + org.springframework.boot + spring-boot-starter-actuator + + + diff --git a/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/src/main/java/cn/hippo4j/example/config/consul/ConfigConsulExampleApplication.java b/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/src/main/java/cn/hippo4j/example/config/consul/ConfigConsulExampleApplication.java new file mode 100644 index 00000000..550acd64 --- /dev/null +++ b/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/src/main/java/cn/hippo4j/example/config/consul/ConfigConsulExampleApplication.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.example.config.consul; + +import cn.hippo4j.core.enable.EnableDynamicThreadPool; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@EnableDynamicThreadPool +@SpringBootApplication(scanBasePackages = "cn.hippo4j.example") +public class ConfigConsulExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(ConfigConsulExampleApplication.class, args); + } +} diff --git a/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/src/main/resources/bootstrap.yml b/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..12d353de --- /dev/null +++ b/hippo4j-example/hippo4j-config-consul-spring-boot-starter-example/src/main/resources/bootstrap.yml @@ -0,0 +1,18 @@ +server: + port: 8091 + +spring: + application: + name: hippo4j-config-consul-spring-boot-starter-example + profiles: + active: dev + cloud: + consul: + host: 127.0.0.1 + port: 8500 + config: + enabled: true + format: yaml + data-key: hippo4j-consul + default-context: application + prefix: config diff --git a/hippo4j-example/pom.xml b/hippo4j-example/pom.xml index 80999ea3..0a3a623e 100644 --- a/hippo4j-example/pom.xml +++ b/hippo4j-example/pom.xml @@ -21,6 +21,7 @@ hippo4j-config-nacos-spring-boot-starter-example hippo4j-config-apollo-spring-boot-starter-example hippo4j-config-zookeeper-spring-boot-starter-example + hippo4j-config-consul-spring-boot-starter-example hippo4j-spring-boot-starter-adapter-rabbitmq-example hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rabbitmq-example hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rocketmq-example diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/pom.xml b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/pom.xml index 837a1f3b..5302d378 100644 --- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/pom.xml +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/pom.xml @@ -47,6 +47,13 @@ ${apollo.version} true + + org.springframework.cloud + spring-cloud-starter-consul-config + ${consul.version} + compile + true + org.apache.curator curator-framework diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/ConfigHandlerConfiguration.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/ConfigHandlerConfiguration.java index 21fa48f4..4c1dac08 100644 --- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/ConfigHandlerConfiguration.java +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/ConfigHandlerConfiguration.java @@ -30,6 +30,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.consul.config.ConsulConfigProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -45,6 +46,8 @@ public class ConfigHandlerConfiguration { private static final String APOLLO_NAMESPACE_KEY = "apollo.namespace"; + private static final String CONSUL_DATA_KEY = "consul.data-key"; + private static final String ZOOKEEPER_CONNECT_STR_KEY = "zookeeper.zk-connect-str"; private static final String ETCD = "etcd.endpoints"; @@ -89,6 +92,16 @@ public class ConfigHandlerConfiguration { } } + @ConditionalOnClass(ConsulConfigProperties.class) + @ConditionalOnProperty(prefix = BootstrapConfigProperties.PREFIX, name = CONSUL_DATA_KEY) + static class EmbeddedConsul { + + @Bean + public ConsulRefresherHandler consulRefresher() { + return new ConsulRefresherHandler(); + } + } + @ConditionalOnClass(CuratorFramework.class) @ConditionalOnProperty(prefix = BootstrapConfigProperties.PREFIX, name = ZOOKEEPER_CONNECT_STR_KEY) static class EmbeddedZookeeper { diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/ConsulRefresherHandler.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/ConsulRefresherHandler.java new file mode 100644 index 00000000..69b60ffa --- /dev/null +++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/ConsulRefresherHandler.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.springboot.starter.refresher; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.springframework.boot.env.OriginTrackedMapPropertySource; +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; +import org.springframework.cloud.bootstrap.config.BootstrapPropertySource; +import org.springframework.cloud.consul.config.ConsulPropertySource; +import org.springframework.cloud.context.environment.EnvironmentChangeEvent; +import org.springframework.context.event.EventListener; +import org.springframework.core.env.AbstractEnvironment; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Consul refresher handler. + */ +@Slf4j +public class ConsulRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh { + + @EventListener(EnvironmentChangeEvent.class) + public void refreshed(EnvironmentChangeEvent event) { + Map configInfo = extractLatestConfigInfo(event); + dynamicRefresh(StringUtils.EMPTY, configInfo); + } + + private Map extractLatestConfigInfo(EnvironmentChangeEvent event) { + AbstractEnvironment environment = (AbstractEnvironment) ((AnnotationConfigServletWebServerApplicationContext) event.getSource()).getEnvironment(); + String activeProfile = Optional.ofNullable(environment.getActiveProfiles().length > 0 ? environment.getActiveProfiles()[0] : null) + .orElseGet(() -> String.valueOf(getApplicationConfigDefaultContext(environment))); + List> bootstrapPropertySourceList = environment.getPropertySources().stream() + .filter(propertySource -> propertySource instanceof BootstrapPropertySource) + .map(propertySource -> (BootstrapPropertySource) propertySource).collect(Collectors.toList()); + Optional> bootstrapPropertySource = bootstrapPropertySourceList.stream() + .filter(source -> source.getName().contains(activeProfile) && source.getPropertyNames().length != 0).findFirst(); + Map configInfo = new HashMap<>(64); + if (bootstrapPropertySource.isPresent()) { + ConsulPropertySource consulPropertySource = (ConsulPropertySource) bootstrapPropertySource.get().getDelegate(); + String[] propertyNames = consulPropertySource.getPropertyNames(); + for (String propertyName : propertyNames) { + configInfo.put(propertyName, consulPropertySource.getProperty(propertyName)); + } + } + return configInfo; + } + + private CharSequence getApplicationConfigDefaultContext(AbstractEnvironment environment) { + return environment.getPropertySources().stream() + .filter(propertySource -> propertySource instanceof OriginTrackedMapPropertySource) + .map(propertySource -> ((Map) propertySource.getSource()).get("spring.cloud.consul.config.default-context")) + .findFirst().orElse(StringUtils.EMPTY); + } + + /** + * TODO consul已实现,暂时不重写 + * @return + */ + @Override + public String getProperties() { + return null; + } + + @Override + public void afterPropertiesSet() {} +} diff --git a/pom.xml b/pom.xml index b2de7eed..9b1e8e29 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,7 @@ 3.4.2 2.3.2.RELEASE 1.9.1 + 2.2.4.RELEASE 0.7.3 1.7.2 2.2.2