Commit b2252846 authored by 黎博's avatar 黎博

新增阿波罗配置

parent 487209c0
......@@ -67,6 +67,11 @@
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
......@@ -100,6 +105,12 @@
<version>4.5.12</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
<build>
......
package cn.qg.holmes;
import cn.qg.holmes.config.ApolloPropertySourceInitializer;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(value = "cn.qg.holmes.mapper")
@MapperScan(value = "cn.qg.holmes.mapper.*")
public class HolmesApplication {
public static void main(String[] args) {
SpringApplication.run(HolmesApplication.class, args);
// SpringApplication.run(HolmesApplication.class, args);
SpringApplication springApplication = new SpringApplication(HolmesApplication.class);
springApplication.addInitializers(new ApolloPropertySourceInitializer());
springApplication.run(args);
}
}
package cn.qg.holmes.config;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.build.ApolloInjector;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.internals.ConfigServiceLocator;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigRegistrar;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import com.ctrip.framework.apollo.util.http.HttpRequest;
import com.ctrip.framework.apollo.util.http.HttpResponse;
import com.ctrip.framework.apollo.util.http.HttpUtil;
import com.ctrip.framework.foundation.Foundation;
import com.ctrip.framework.foundation.internals.provider.DefaultApplicationProvider;
import com.ctrip.framework.foundation.internals.provider.DefaultServerProvider;
import com.google.common.collect.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
@Configuration
@EnableApolloConfig
@Import(ApolloConfigRegistrar.class)
public class ApolloPropertySourceInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
private int order = Ordered.HIGHEST_PRECEDENCE + 5;
private final Multimap<Integer, String> NAMESPACE_NAMES = HashMultimap.create();
private static final Logger logger = LoggerFactory.getLogger(ConfigServiceLocator.class);
private static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE;
private static final String DEFAULT_NAMESPACE = ConfigConsts.NAMESPACE_APPLICATION;
//todo 需要补充服务地址. 暂时测试
public ApolloPropertySourceInitializer() {
this(Integer.parseInt(Foundation.app().getProperty("order", String.valueOf(DEFAULT_ORDER))),
StringUtils.commaDelimitedListToStringArray(Foundation.app().getProperty("namespace", DEFAULT_NAMESPACE)));
}
public ApolloPropertySourceInitializer(String... namespace) {
this(DEFAULT_ORDER, namespace);
}
public ApolloPropertySourceInitializer(int order, String... namespace) {
ArrayList<String> namespaceArr = Lists.newArrayList(namespace);
if (!namespaceArr.contains(DEFAULT_NAMESPACE)) {
NAMESPACE_NAMES.putAll(DEFAULT_ORDER, Lists.newArrayList(DEFAULT_NAMESPACE));
}
NAMESPACE_NAMES.putAll(order, namespaceArr);
}
@Override
public int getOrder() {
return this.order;
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
if (environment.getPropertySources().contains("ApolloPropertySources")) {
return;
}
initIpAndNamespace(environment);
initKubernetesEnv(environment);
logger.info("Fetching remote config by apollo and try to reinitialize logging system if necessary.");
CompositePropertySource composite = new CompositePropertySource("ApolloPropertySources");
ImmutableSortedSet<Integer> orders = ImmutableSortedSet.copyOf(NAMESPACE_NAMES.keySet());
UnmodifiableIterator iterator = orders.iterator();
while (iterator.hasNext()) {
int order = ((Integer) iterator.next()).intValue();
Iterator it = NAMESPACE_NAMES.get(order).iterator();
while (it.hasNext()) {
String namespace = (String) it.next();
Config config = ConfigService.getConfig(namespace);
composite.addPropertySource(new ConfigPropertySource(namespace, config));
}
}
environment.getPropertySources().addFirst(composite);
//reinitialize logging system.
reinitializeLoggingSystem(environment);
DefaultApplicationProvider defaultApplicationProvider = new DefaultApplicationProvider();
defaultApplicationProvider.initialize();
DefaultServerProvider defaultServerProvider = new DefaultServerProvider();
defaultServerProvider.initialize();
}
/**
* 初始化 tech.localhost 参数
* 初始化 NAMESPACE 参数
*
* @param environment
*/
private void initIpAndNamespace(ConfigurableEnvironment environment) {
//获取本机 IP
String localhost = environment.getProperty("tech.localhost", Foundation.app().getProperty("tech.localhost", null));
if (StringUtils.isEmpty(localhost)) {
localhost = Foundation.net().getHostAddress();
} else {
logger.warn("获取 tech.localhost 信息结果 : {}, 测试环境应为本机IP", localhost);
}
environment.getSystemProperties().put("tech.localhost", localhost);
//如果不存在命名空间, 本机 IP 的后缀当做命名空间.
String[] ipSplit = localhost.split("\\.");
String localNamespace = environment.getProperty("NAMESPACE", ipSplit[ipSplit.length - 1]);
environment.getSystemProperties().putIfAbsent("NAMESPACE", localNamespace);
}
private void initKubernetesEnv(ConfigurableEnvironment environment) {
//如果系统中存在namespace, 那我们什么都不做好了. 这时候应该是 kubernetes 环境
if (System.getenv("NAMESPACE") != null) {
//do nothing
logger.info("运行在 kubernets 环境.");
return;
}
boolean isPro = Env.PRO.name().equalsIgnoreCase(Foundation.server().getEnvType());
//如果是生产环境, 我也啥都不干. 太吓人了.
if (isPro) {
logger.info("哇, 生产环境. 配置中心静悄悄. 什么都不敢做.");
return;
}
String namespace = environment.getProperty("NAMESPACE", Foundation.app().getProperty("NAMESPACE", null));
if (namespace == null) {
logger.info("你好像没有配置 NAMESPACE 哦?你不打算连接到 kubernetes 内部么?");
return;
}
HttpUtil httpUtil = ApolloInjector.getInstance(HttpUtil.class);
String kubernetesServer = Foundation.app().getProperty("eos_server_host", "http://eos.quantgroups.com/");
HttpRequest httpRequest = new HttpRequest(kubernetesServer + "api/apollo/env_vars?namespace=" + namespace);
HttpResponse<KubeEnvInfo> mapHttpResponse = httpUtil.doGet(httpRequest, KubeEnvInfo.class);
KubeEnvInfo body = mapHttpResponse.getBody();
if (body != null && body.success) {
logger.info("客官请放心, kubernets 的环境变量已经注入, 您可以放心的在 kubernetes 之外启动你的服务了");
environment.getSystemProperties().putAll(body.details);
return;
}
logger.error("额... 看起来 kubernetes server 有点问题, 返回了false, serverInfo:{} ,body:{}", kubernetesServer, body);
}
private static class KubeEnvInfo {
boolean success;
Map<String, String> details;
}
private void reinitializeLoggingSystem(ConfigurableEnvironment environment) {
Iterable<ConfigurationPropertySource> sources = ConfigurationPropertySources.get(environment);
Binder binder = new Binder(sources);
BindResult<Properties> bindResult = binder.bind( "",Properties.class);
Properties properties = bindResult.get();
Set<Object> keys = new HashSet<>();
properties.forEach((i,j)->{
keys.add(i);
});
if (!keys.stream().filter(i->StringUtils.startsWithIgnoreCase((String) i,"logging.")).collect(Collectors.toSet()).isEmpty()) {
String logConfig = environment.resolvePlaceholders("${logging.config:}");
LogFile logFile = LogFile.get(environment);
LoggingSystem system = LoggingSystem
.get(LoggingSystem.class.getClassLoader());
try {
ResourceUtils.getURL(logConfig).openStream().close();
// Three step initialization that accounts for the clean up of the logging
// context before initialization. Spring Boot doesn't initialize a logging
// system that hasn't had this sequence applied (since 1.4.1).
system.cleanUp();
system.beforeInitialize();
system.initialize(new LoggingInitializationContext(environment),
logConfig, logFile);
} catch (Exception ex) {
ApolloPropertySourceInitializer.logger
.warn("Logging config file location '" + logConfig
+ "' cannot be opened and will be ignored");
}
}
}
}
package cn.qg.holmes.config;
import com.ctrip.framework.apollo.Config;
import org.springframework.core.env.EnumerablePropertySource;
import java.util.Set;
public class ConfigPropertySource extends EnumerablePropertySource<Config> {
private static final String[] EMPTY_ARRAY = new String[0];
public ConfigPropertySource(String name, Config source) {
super(name, source);
}
@Override
public String[] getPropertyNames() {
Set<String> propertyNames = this.source.getPropertyNames();
if (propertyNames.isEmpty()) {
return EMPTY_ARRAY;
}
return propertyNames.toArray(new String[propertyNames.size()]);
}
@Override
public Object getProperty(String name) {
return this.source.getProperty(name, null);
}
}
package cn.qg.holmes.config;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* 数据源设置
* @author libo 2021-03-20
*/
@Configuration
public class DataSourceConfiguration {
@Value("${holmes.data.mysql.jdbc-url}")
private String holmesJdbcUrl;
@Value("${holmes.data.mysql.user}")
private String user;
@Value("${holmes.data.mysql.password}")
private String password;
@Value("${holmes.data.mysql.max-pool-size}")
private Integer maxPoolSize;
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(holmesJdbcUrl);
config.setUsername(user);
config.setPassword(password);
config.setMaximumPoolSize(maxPoolSize);
config.setMinimumIdle(20);
config.setMinimumIdle(20);
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
return new HikariDataSource(config);
}
}
......@@ -2,9 +2,13 @@ package cn.qg.holmes.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author libo 2021-03-20
*/
@Configuration
public class MybatisPlusConfig {
......@@ -22,4 +26,6 @@ public class MybatisPlusConfig {
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
}
package cn.qg.holmes.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
/**
* @author libo 2021-03-20
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Value("${holmes.redis.host}")
private String host;
@Value("${holmes.redis.port}")
private int port;
@Value("${holmes.redis.database}")
private int database;
@Bean
public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setDatabase(database);
JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb =
(JedisClientConfiguration.JedisPoolingClientConfigurationBuilder)JedisClientConfiguration.builder();
jpcb.poolConfig(jedisPoolConfig);
JedisClientConfiguration jedisClientConfiguration = jpcb.build();
return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
}
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(32);
jedisPoolConfig.setMaxIdle(16);
jedisPoolConfig.setMinIdle(8);
jedisPoolConfig.setMaxWaitMillis(5000);
jedisPoolConfig.setTestOnBorrow(true);
return jedisPoolConfig;
}
/**
* 配置自定义redisTemplate
*/
......
app.id=holmes
namespace=application,tech.service.urls,tech.common,tech.sleuth,tech.deploy,tech.msg.sdk
apollo.meta=http://apollo-dev.quantgroups.com
\ No newline at end of file
local.meta=http://localhost:8080
dev.meta=http://apollo-dev.quantgroups.com
fat.meta=http://someIp:8080
uat.meta=http://anotherIp:8080
lpt.meta=${lpt_meta}
pro.meta=http://apollo-pro.quantgroups.com
\ No newline at end of file
spring:
datasource:
url: jdbc:mysql://172.17.5.5:32178/holmes
username: qa
password: qatest
driver-class-name: com.mysql.jdbc.Driver
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
redis:
host: 172.17.5.12
port: 32236
database: 0
jedis:
pool:
max-active: 8
max-wait: -1
max-idle: 8
application:
name: holmes
server:
port: 8084
#spring:
# datasource:
# url: jdbc:mysql://172.17.5.5:32178/holmes
# username: qa
# password: qatest
# driver-class-name: com.mysql.jdbc.Driver
# jackson:
# date-format: yyyy-MM-dd HH:mm:ss
# time-zone: GMT+8
# redis:
# host: 172.17.5.12
# port: 32236
# database: 0
# jedis:
# pool:
# max-active: 8
# max-wait: -1
# max-idle: 8
# application:
# name: holmes
#
#server:
# port: 8084
mybatis-plus:
mapper-locations: classpath:mapper/*/*.xml
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment