实现内嵌的 apollo 的配置中心的支持

This commit is contained in:
YunaiV 2021-01-20 17:12:27 +08:00
parent 6bed7778e8
commit c4c614592a
13 changed files with 220 additions and 6 deletions

View File

@ -167,6 +167,13 @@
<version>${redisson.version}</version>
</dependency>
<!-- -->
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.7.0</version>
</dependency>
<!-- 监控相关 -->
<dependency>
<groupId>org.apache.skywalking</groupId>

View File

@ -0,0 +1,95 @@
package cn.iocoder.dashboard.framework.apollo.internals;
import com.ctrip.framework.apollo.Apollo;
import com.ctrip.framework.apollo.build.ApolloInjector;
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
import com.ctrip.framework.apollo.enums.ConfigSourceType;
import com.ctrip.framework.apollo.internals.AbstractConfigRepository;
import com.ctrip.framework.apollo.internals.ConfigRepository;
import com.ctrip.framework.apollo.tracer.Tracer;
import com.ctrip.framework.apollo.util.ConfigUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@Slf4j
public class DBConfigRepository extends AbstractConfigRepository {
private final static ScheduledExecutorService m_executorService;
static {
m_executorService = Executors.newScheduledThreadPool(1,
ApolloThreadFactory.create(DBConfigRepository.class.getSimpleName(), true));
}
private final ConfigUtil m_configUtil;
private final AtomicReference<Properties> m_configCache;
private final String m_namespace;
public DBConfigRepository(String namespace) {
// 初始化变量
this.m_namespace = namespace;
m_configCache = new AtomicReference<>();
m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);
// 初始化加载
this.trySync();
// 初始化定时任务
this.schedulePeriodicRefresh();
}
private AtomicInteger index = new AtomicInteger();
@Override
protected void sync() {
System.out.println("我同步啦");
index.incrementAndGet();
Properties properties = new Properties();
properties.setProperty("demo.test", String.valueOf(index.get()));
m_configCache.set(properties);
super.fireRepositoryChange(m_namespace, properties);
}
@Override
public Properties getConfig() {
// 兜底避免可能存在配置为 null 的情况
if (m_configCache.get() == null) {
this.trySync();
}
// 返回配置
return m_configCache.get();
}
@Override
public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) {
// 啥事不做
}
@Override
public ConfigSourceType getSourceType() {
return ConfigSourceType.REMOTE;
}
private void schedulePeriodicRefresh() {
log.debug("Schedule periodic refresh with interval: {} {}",
m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit());
m_executorService.scheduleAtFixedRate(() -> {
Tracer.logEvent("Apollo.ConfigService", String.format("periodicRefresh: %s", m_namespace));
log.debug("refresh config for namespace: {}", m_namespace);
// 执行同步
trySync();
Tracer.logEvent("Apollo.Client.Version", Apollo.VERSION);
}, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(),
m_configUtil.getRefreshIntervalTimeUnit());
// TimeUnit.SECONDS);
}
}

View File

@ -0,0 +1,75 @@
package cn.iocoder.dashboard.framework.apollo.internals;
import cn.iocoder.dashboard.framework.apollo.spi.DBConfigFactory;
import com.ctrip.framework.apollo.exceptions.ApolloConfigException;
import com.ctrip.framework.apollo.internals.*;
import com.ctrip.framework.apollo.spi.*;
import com.ctrip.framework.apollo.tracer.Tracer;
import com.ctrip.framework.apollo.util.ConfigUtil;
import com.ctrip.framework.apollo.util.factory.DefaultPropertiesFactory;
import com.ctrip.framework.apollo.util.factory.PropertiesFactory;
import com.ctrip.framework.apollo.util.http.HttpUtil;
import com.ctrip.framework.apollo.util.yaml.YamlParser;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Singleton;
/**
* Guice injector
*
* 基于 Guice 注入器实现类
*
* @author Jason Song(song_s@ctrip.com)
*/
public class DefaultXInjector implements Injector {
private final com.google.inject.Injector m_injector;
public DefaultXInjector() {
try {
m_injector = Guice.createInjector(new ApolloModule());
} catch (Throwable ex) {
ApolloConfigException exception = new ApolloConfigException("Unable to initialize Guice Injector!", ex);
Tracer.logError(exception);
throw exception;
}
}
@Override
public <T> T getInstance(Class<T> clazz) {
try {
return m_injector.getInstance(clazz);
} catch (Throwable ex) {
Tracer.logError(ex);
throw new ApolloConfigException(String.format("Unable to load instance for %s!", clazz.getName()), ex);
}
}
@Override
public <T> T getInstance(Class<T> clazz, String name) {
// Guice does not support get instance by type and name
return null;
}
private static class ApolloModule extends AbstractModule {
@Override
protected void configure() {
bind(ConfigManager.class).to(DefaultConfigManager.class).in(Singleton.class);
bind(ConfigFactoryManager.class).to(DefaultConfigFactoryManager.class).in(Singleton.class);
bind(ConfigRegistry.class).to(DefaultConfigRegistry.class).in(Singleton.class);
// 自定义 ConfigFactory 实现使用 DB 作为数据源
bind(ConfigFactory.class).to(DBConfigFactory.class).in(Singleton.class);
bind(ConfigUtil.class).in(Singleton.class);
bind(HttpUtil.class).in(Singleton.class);
bind(ConfigServiceLocator.class).in(Singleton.class);
bind(RemoteConfigLongPollService.class).in(Singleton.class);
bind(YamlParser.class).in(Singleton.class);
bind(PropertiesFactory.class).to(DefaultPropertiesFactory.class).in(Singleton.class);
}
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.dashboard.framework.apollo;

View File

@ -0,0 +1,27 @@
package cn.iocoder.dashboard.framework.apollo.spi;
import cn.iocoder.dashboard.framework.apollo.internals.DBConfigRepository;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigFile;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.ctrip.framework.apollo.internals.ConfigRepository;
import com.ctrip.framework.apollo.internals.DefaultConfig;
import com.ctrip.framework.apollo.spi.ConfigFactory;
public class DBConfigFactory implements ConfigFactory {
@Override
public Config create(String namespace) {
return new DefaultConfig(namespace, this.createDBConfigRepository(namespace));
}
@Override
public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat) {
throw new UnsupportedOperationException("暂不支持 Apollo 配置文件");
}
private ConfigRepository createDBConfigRepository(String namespace) {
return new DBConfigRepository(namespace); // TODO 芋艿看看怎么优化
}
}

View File

@ -28,7 +28,7 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.CO
@RequestMapping("/system/config")
public class SysConfigController {
@Value("${demo.test:false}")
@Value("${demo.test}")
private String demo;
@GetMapping("/demo")

View File

@ -8,8 +8,8 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRo
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.lang.Nullable;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;

View File

@ -6,8 +6,8 @@ import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostExport
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostPageReqVO;
import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostUpdateReqVO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysPostDO;
import org.springframework.lang.Nullable;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;

View File

@ -1,8 +1,8 @@
package cn.iocoder.dashboard.modules.system.service.permission;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
import org.springframework.lang.Nullable;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Set;

View File

@ -6,8 +6,8 @@ import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.SysRole
import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.SysRolePageReqVO;
import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.SysRoleUpdateReqVO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
import org.springframework.lang.Nullable;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Set;

View File

@ -18,11 +18,11 @@ import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

View File

@ -0,0 +1 @@
cn.iocoder.dashboard.framework.apollo.internals.DefaultXInjector

View File

@ -47,6 +47,14 @@ yudao:
file:
base-path: http://127.0.0.1:1024/api/file/get/
# Apollo 配置中心
apollo:
bootstrap:
enabled: true
eagerLoad:
enabled: true
autoUpdateInjectedSpringProperties: true
# MyBatis Plus 的配置项
mybatis-plus:
configuration: