Support for Consul Configuration Center to dynamically adjust parameters

pull/1007/head
Li 3 years ago
parent 190de72dfe
commit 6a0d229c3f

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-example</artifactId>
<version>${revision}</version>
</parent>
<artifactId>hippo4j-config-consul-spring-boot-starter-example</artifactId>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-example-core</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-config-spring-boot-starter</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<version>${consul.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

@ -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.config.consul")
public class ConfigConsulExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigConsulExampleApplication.class, args);
}
}

@ -0,0 +1,41 @@
/*
* 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.config;
import cn.hippo4j.core.executor.DynamicThreadPool;
import cn.hippo4j.core.executor.support.ThreadPoolBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ThreadPoolExecutor;
/**
* Dynamic thread-pool config.
*/
@Slf4j
@Configuration
public class DynamicThreadPoolConfig {
@Bean
@DynamicThreadPool
public ThreadPoolExecutor messageConsumeDynamicExecutor() {
String threadPoolId = "message-consume";
return ThreadPoolBuilder.buildDynamicPoolById(threadPoolId);
}
}

@ -0,0 +1,25 @@
package cn.hippo4j.example.config.consul.controller;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@RestController
public class TestController {
@Resource
private ThreadPoolExecutor messageConsumeDynamicExecutor;
@GetMapping("/hippo4j-consul/test")
public int test() {
int maximumPoolSize = messageConsumeDynamicExecutor.getMaximumPoolSize();
int corePoolSize = messageConsumeDynamicExecutor.getCorePoolSize();
log.info("corePoolSize: {}, maximumPoolSize: {}", corePoolSize, maximumPoolSize);
return corePoolSize + maximumPoolSize;
}
}

@ -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
prefixes: config

@ -21,6 +21,7 @@
<module>hippo4j-config-nacos-spring-boot-starter-example</module>
<module>hippo4j-config-apollo-spring-boot-starter-example</module>
<module>hippo4j-config-zookeeper-spring-boot-starter-example</module>
<module>hippo4j-config-consul-spring-boot-starter-example</module>
<module>hippo4j-spring-boot-starter-adapter-rabbitmq-example</module>
<module>hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rabbitmq-example</module>
<module>hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rocketmq-example</module>

@ -47,6 +47,13 @@
<version>${apollo.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<version>${consul.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>

@ -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 {

@ -72,4 +72,13 @@ public abstract class AbstractConfigThreadPoolDynamicRefresh implements ThreadPo
log.error("Hippo-4J core dynamic refresh failed.", ex);
}
}
public void dynamicRefresh(Map<Object, Object> configInfo) {
try {
BootstrapConfigProperties binderCoreProperties = bootstrapConfigPropertiesBinderAdapt.bootstrapCorePropertiesBinder(configInfo, bootstrapConfigProperties);
ApplicationContextHolder.getInstance().publishEvent(new Hippo4jConfigDynamicRefreshEvent(this, binderCoreProperties));
} catch (Exception ex) {
log.error("Hippo-4J core dynamic refresh failed.", ex);
}
}
}

@ -0,0 +1,82 @@
/*
* 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.springframework.beans.factory.annotation.Value;
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 {
private static final String CONSUL_PROPERTY = "${spring.dynamic.thread-pool.consul.data-key}";
@Value(CONSUL_PROPERTY)
private String dataKey;
@EventListener(EnvironmentChangeEvent.class)
public void refreshed(EnvironmentChangeEvent event) {
String[] dataKeys = this.dataKey.split(",");
this.dataKey = dataKeys[0];
AbstractEnvironment environment = (AbstractEnvironment) ((AnnotationConfigServletWebServerApplicationContext) event.getSource()).getEnvironment();
List<BootstrapPropertySource<?>> bootstrapPropertySourceList = environment.getPropertySources().stream()
.filter(propertySource -> propertySource instanceof BootstrapPropertySource)
.map(propertySource -> (BootstrapPropertySource<?>) propertySource).collect(Collectors.toList());
Optional<BootstrapPropertySource<?>> bootstrapPropertySource = bootstrapPropertySourceList.stream()
.filter(source -> source.getName().contains(environment.getActiveProfiles()[0])
&& source.getPropertyNames().length != 0).findFirst();
Map<Object, Object> 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));
}
}
dynamicRefresh(configInfo);
}
@Override
public String getProperties() {
return null;
}
@Override
public void afterPropertiesSet() {}
}

@ -61,6 +61,7 @@
<mybatis-plus.version>3.4.2</mybatis-plus.version>
<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<apollo.version>1.9.1</apollo.version>
<consul.version>2.2.4.RELEASE</consul.version>
<jetcd.version>0.7.3</jetcd.version>
<polaris.version>1.7.2</polaris.version>
<rocketmq.version>2.2.2</rocketmq.version>

Loading…
Cancel
Save