Merge pull request #120 from weihubeats/develop

添加 apollo动态刷新线程池
pull/123/head
龙台 Long Tai 2 years ago committed by GitHub
commit 018554ee07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -54,6 +54,15 @@
<version>2.2.5.RELEASE</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>${apollo.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>

@ -1,5 +1,6 @@
package cn.hippo4j.core.starter.config;
import cn.hippo4j.core.starter.parser.ConfigFileTypeEnum;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ -38,7 +39,7 @@ public class BootstrapCoreProperties {
/**
* Config file type.
*/
private String configFileType;
private ConfigFileTypeEnum configFileType;
/**
* Nacos config.

@ -12,18 +12,17 @@ import cn.hippo4j.common.notify.platform.WeChatSendMessageHandler;
import cn.hippo4j.core.config.UtilAutoConfiguration;
import cn.hippo4j.core.executor.ThreadPoolNotifyAlarmHandler;
import cn.hippo4j.core.starter.notify.CoreNotifyConfigBuilder;
import cn.hippo4j.core.starter.parser.ConfigParserHandler;
import cn.hippo4j.core.starter.refresher.ApolloRefresherHandler;
import cn.hippo4j.core.starter.refresher.NacosCloudRefresherHandler;
import cn.hippo4j.core.starter.refresher.NacosRefresherHandler;
import cn.hippo4j.core.starter.refresher.config.ConfigParser;
import cn.hippo4j.core.starter.refresher.config.impl.PropConfigParser;
import cn.hippo4j.core.starter.refresher.config.impl.YmlConfigParser;
import cn.hippo4j.core.starter.support.DynamicThreadPoolPostProcessor;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.ConfigService;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
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.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@ -31,8 +30,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import java.util.List;
/**
* Dynamic thread pool auto configuration.
*
@ -51,8 +48,7 @@ public class DynamicThreadPoolCoreAutoConfiguration {
private static final String NACOS_CONFIG_KEY = "com.alibaba.nacos.api.config";
private final List<String> yamlList = Lists.newArrayList("yaml", "yml");
private final List<String> propList = Lists.newArrayList("properties");
private static final String APOLLO_CONFIG_KEY = "com.ctrip.framework.apollo.ConfigService.class";
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
@ -106,32 +102,25 @@ public class DynamicThreadPoolCoreAutoConfiguration {
@ConditionalOnMissingClass(NACOS_CONFIG_MANAGER_KEY)
public NacosRefresherHandler nacosRefresherHandler(ConfigService configService,
ThreadPoolNotifyAlarmHandler threadPoolNotifyAlarmHandler,
ConfigParser configParser,
BootstrapCoreProperties bootstrapCoreProperties) {
return new NacosRefresherHandler(configService, threadPoolNotifyAlarmHandler, configParser, bootstrapCoreProperties);
return new NacosRefresherHandler(configService, threadPoolNotifyAlarmHandler, bootstrapCoreProperties);
}
@Bean
@ConditionalOnClass(name = NACOS_CONFIG_MANAGER_KEY)
public NacosCloudRefresherHandler nacosCloudRefresherHandler(NacosConfigManager nacosConfigManager,
ThreadPoolNotifyAlarmHandler threadPoolNotifyAlarmHandler,
ConfigParser configParser,
BootstrapCoreProperties bootstrapCoreProperties) {
return new NacosCloudRefresherHandler(nacosConfigManager, threadPoolNotifyAlarmHandler, configParser, bootstrapCoreProperties);
return new NacosCloudRefresherHandler(nacosConfigManager, threadPoolNotifyAlarmHandler, bootstrapCoreProperties);
}
@Bean
public ConfigParser configParserHandler() {
// return new ConfigParserHandler();
String configFileType = bootstrapCoreProperties.getConfigFileType();
if (yamlList.contains(configFileType)) {
return new YmlConfigParser();
}
if (propList.contains(configFileType)) {
return new PropConfigParser();
}
throw new UnsupportedOperationException("暂不支持的配置文件类型: " + configFileType);
@ConditionalOnMissingBean
@ConditionalOnClass(name = APOLLO_CONFIG_KEY)
public ApolloRefresherHandler apolloRefresher(ThreadPoolNotifyAlarmHandler threadPoolNotifyAlarmHandler,
BootstrapCoreProperties bootstrapCoreProperties) {
return new ApolloRefresherHandler(threadPoolNotifyAlarmHandler, bootstrapCoreProperties);
}
}

@ -0,0 +1,15 @@
package cn.hippo4j.core.starter.parser;
/**
* @author : wh
* @date : 2022/3/1 07:50
* @description:
*/
public abstract class AbstractConfigParser implements ConfigParser{
@Override
public boolean supports(ConfigFileTypeEnum type) {
return getConfigFileTypes().contains(type);
}
}

@ -0,0 +1,35 @@
package cn.hippo4j.core.starter.parser;
import lombok.Getter;
/**
* @author : wh
* @date : 2022/3/1 07:47
* @description:
*/
@Getter
public enum ConfigFileTypeEnum {
PROPERTIES("properties"),
XML("xml"),
JSON("json"),
YML("yml"),
YAML("yaml"),
TXT("txt");
private final String value;
ConfigFileTypeEnum(String value) {
this.value = value;
}
public static ConfigFileTypeEnum of(String value) {
for (ConfigFileTypeEnum typeEnum : ConfigFileTypeEnum.values()) {
if (typeEnum.value.equals(value)) {
return typeEnum;
}
}
return PROPERTIES;
}
}

@ -0,0 +1,20 @@
package cn.hippo4j.core.starter.parser;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author : wh
* @date : 2022/3/1 07:47
* @description:
*/
public interface ConfigParser {
boolean supports(ConfigFileTypeEnum type);
Map<Object, Object> doParse(String content) throws IOException;
List<ConfigFileTypeEnum> getConfigFileTypes();
}

@ -0,0 +1,47 @@
package cn.hippo4j.core.starter.parser;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
/**
* @author : wh
* @date : 2022/3/1 08:02
* @description:
*/
public class ConfigParserHandler {
private static final List<ConfigParser> PARSERS = Lists.newArrayList();
private ConfigParserHandler() {
ServiceLoader<ConfigParser> loader = ServiceLoader.load(ConfigParser.class);
for (ConfigParser configParser : loader) {
PARSERS.add(configParser);
}
PARSERS.add(new PropertiesConfigParser());
PARSERS.add(new YamlConfigParser());
}
public Map<Object, Object> parseConfig(String content, ConfigFileTypeEnum type) throws IOException {
for (ConfigParser parser : PARSERS) {
if (parser.supports(type)) {
return parser.doParse(content);
}
}
return Collections.emptyMap();
}
public static ConfigParserHandler getInstance() {
return ConfigParserHandlerHolder.INSTANCE;
}
private static class ConfigParserHandlerHolder {
private static final ConfigParserHandler INSTANCE = new ConfigParserHandler();
}
}

@ -0,0 +1,30 @@
package cn.hippo4j.core.starter.parser;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* @author : wh
* @date : 2022/3/1 07:49
* @description:
*/
public class PropertiesConfigParser extends AbstractConfigParser{
@Override
public Map<Object, Object> doParse(String content) throws IOException {
Properties properties = new Properties();
properties.load(new StringReader(content));
return properties;
}
@Override
public List<ConfigFileTypeEnum> getConfigFileTypes() {
return Lists.newArrayList(ConfigFileTypeEnum.PROPERTIES);
}
}

@ -0,0 +1,33 @@
package cn.hippo4j.core.starter.parser;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Map;
/**
* @author : wh
* @date : 2022/3/1 07:57
* @description:
*/
public class YamlConfigParser extends AbstractConfigParser{
@Override
public Map<Object, Object> doParse(String content) {
if (StringUtils.isEmpty(content)) {
return Maps.newHashMapWithExpectedSize(0);
}
YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean();
bean.setResources(new ByteArrayResource(content.getBytes()));
return bean.getObject();
}
@Override
public List<ConfigFileTypeEnum> getConfigFileTypes() {
return Lists.newArrayList(ConfigFileTypeEnum.YML, ConfigFileTypeEnum.YAML);
}
}

@ -9,7 +9,7 @@ import cn.hippo4j.core.executor.support.*;
import cn.hippo4j.core.proxy.RejectedProxyUtil;
import cn.hippo4j.core.starter.config.BootstrapCoreProperties;
import cn.hippo4j.core.starter.config.ExecutorProperties;
import cn.hippo4j.core.starter.refresher.config.ConfigParser;
import cn.hippo4j.core.starter.parser.ConfigParserHandler;
import cn.hippo4j.core.starter.support.GlobalCoreThreadPoolManage;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -18,6 +18,7 @@ import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -41,8 +42,6 @@ public abstract class AbstractCoreThreadPoolDynamicRefresh implements ThreadPool
private final ThreadPoolNotifyAlarmHandler threadPoolNotifyAlarmHandler;
private final ConfigParser configParser;
protected final BootstrapCoreProperties bootstrapCoreProperties;
protected final ExecutorService dynamicRefreshExecutorService = ThreadPoolBuilder.builder()
@ -51,8 +50,15 @@ public abstract class AbstractCoreThreadPoolDynamicRefresh implements ThreadPool
.build();
@Override
public void dynamicRefresh(String content) {
Map<Object, Object> configInfo = configParser.parseConfig(content);
public void dynamicRefresh(String content){
Map<Object, Object> configInfo = null;
try {
configInfo = ConfigParserHandler.getInstance().parseConfig(content, bootstrapCoreProperties.getConfigFileType());
} catch (IOException e) {
log.error("dynamic-thread-pool parse config file error, content: {}, fileType: {}",
content, bootstrapCoreProperties.getConfigFileType(), e);
return;
}
ConfigurationPropertySource sources = new MapConfigurationPropertySource(configInfo);
Binder binder = new Binder(sources);

@ -0,0 +1,50 @@
package cn.hippo4j.core.starter.refresher;
import cn.hippo4j.core.executor.ThreadPoolNotifyAlarmHandler;
import cn.hippo4j.core.starter.config.BootstrapCoreProperties;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigFile;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
/**
* @author : wh
* @date : 2022/2/28 21:32
* @description:
*/
@Slf4j
public class ApolloRefresherHandler extends AbstractCoreThreadPoolDynamicRefresh implements ConfigChangeListener, InitializingBean {
private static final String APOLLO_PROPERTY = "${apollo.bootstrap.namespaces:application}";
@Value(APOLLO_PROPERTY)
private String namespace;
public ApolloRefresherHandler(ThreadPoolNotifyAlarmHandler threadPoolNotifyAlarmHandler , BootstrapCoreProperties bootstrapCoreProperties) {
super(threadPoolNotifyAlarmHandler, bootstrapCoreProperties);
}
@Override
public void onChange(ConfigChangeEvent configChangeEvent) {
ConfigFile configFile = ConfigService.getConfigFile(namespace,
ConfigFileFormat.fromString(bootstrapCoreProperties.getConfigFileType().getValue()));
String configInfo = configFile.getContent();
dynamicRefresh(configInfo);
}
@Override
public void afterPropertiesSet() {
String[] apolloNamespaces = this.namespace.split(",");
this.namespace = apolloNamespaces[0];
Config config = ConfigService.getConfig(namespace);
config.addChangeListener(this);
log.info("dynamic-thread-pool refresher, add apollo listener success, namespace: {}", namespace);
}
}

@ -2,7 +2,6 @@ package cn.hippo4j.core.starter.refresher;
import cn.hippo4j.core.executor.ThreadPoolNotifyAlarmHandler;
import cn.hippo4j.core.starter.config.BootstrapCoreProperties;
import cn.hippo4j.core.starter.refresher.config.ConfigParser;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import lombok.extern.slf4j.Slf4j;
@ -24,9 +23,8 @@ public class NacosCloudRefresherHandler extends AbstractCoreThreadPoolDynamicRef
public NacosCloudRefresherHandler(NacosConfigManager nacosConfigManager,
ThreadPoolNotifyAlarmHandler threadPoolNotifyAlarmHandler,
ConfigParser configParser,
BootstrapCoreProperties bootstrapCoreProperties) {
super(threadPoolNotifyAlarmHandler, configParser, bootstrapCoreProperties);
super(threadPoolNotifyAlarmHandler, bootstrapCoreProperties);
this.nacosConfigManager = nacosConfigManager;
}

@ -2,7 +2,6 @@ package cn.hippo4j.core.starter.refresher;
import cn.hippo4j.core.executor.ThreadPoolNotifyAlarmHandler;
import cn.hippo4j.core.starter.config.BootstrapCoreProperties;
import cn.hippo4j.core.starter.refresher.config.ConfigParser;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import lombok.extern.slf4j.Slf4j;
@ -24,9 +23,8 @@ public class NacosRefresherHandler extends AbstractCoreThreadPoolDynamicRefresh
public NacosRefresherHandler(ConfigService configService,
ThreadPoolNotifyAlarmHandler threadPoolNotifyAlarmHandler,
ConfigParser configParser,
BootstrapCoreProperties bootstrapCoreProperties) {
super(threadPoolNotifyAlarmHandler, configParser, bootstrapCoreProperties);
super(threadPoolNotifyAlarmHandler, bootstrapCoreProperties);
this.configService = configService;
}

@ -47,6 +47,7 @@
<logback.version>1.2.3</logback.version>
<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>
<maven.javadoc.failOnError>false</maven.javadoc.failOnError>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>

Loading…
Cancel
Save