feat: 配置初始化

This commit is contained in:
骑着蜗牛追导弹 2024-12-03 21:49:56 +08:00
parent a2aad2204f
commit 06ebd5c664
15 changed files with 337 additions and 62 deletions

View File

@ -9,13 +9,43 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<netty.version>4.1.115.Final</netty.version>
<protostuff.version>1.3.0</protostuff.version>
<hutool.version>5.8.33</hutool.version>
<configuration.version>1.10</configuration.version>
</properties>
<artifactId>kenaito-config-core</artifactId>
<name>子模块-配置中心sdk</name>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
</dependency>
<!-- protostuff -->
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-api</artifactId>
<version>${protostuff.version}</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>${protostuff.version}</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>${protostuff.version}</version>
</dependency>
<!-- 工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -1,26 +0,0 @@
package cn.odboy.config;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
public class ConfigCenterClient {
private final RestTemplate restTemplate;
private final String configCenterUrl;
public ConfigCenterClient(String configCenterUrl) {
this.restTemplate = new RestTemplate();
this.configCenterUrl = configCenterUrl;
}
public Map<String, Object> fetchConfig() {
ResponseEntity<Map> response = restTemplate.getForEntity(configCenterUrl, Map.class);
if (response.getStatusCode().is2xxSuccessful()) {
return response.getBody();
} else {
throw new RuntimeException("Failed to fetch config from config center");
}
}
}

View File

@ -1,30 +0,0 @@
package cn.odboy.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import java.util.Map;
/**
* 配置加载器
* @author odboy
* @date 2024-12-03
*/
@Configuration
public class ConfigCenterConfigLoader {
@Bean
public BeanFactoryPostProcessor configLoader(ConfigurableEnvironment environment) {
return new BeanFactoryPostProcessor() {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// ConfigCenterClient client = new ConfigCenterClient("http://your-config-center-url/config");
// Map<String, Object> configKv = client.fetchConfig();
// MapPropertySource propertySource = new MapPropertySource("configCenter", configKv);
// environment.getPropertySources().addFirst(propertySource);
}
};
}
}

View File

@ -10,7 +10,8 @@ import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "kenaito.config-center")
public class ConfigCenterProperties {
private String meta;
private String server;
private Integer port;
private String dataId;
private String cacheDir;
private String env;

View File

@ -0,0 +1,66 @@
package cn.odboy.config.context;
import cn.odboy.config.ConfigCenterProperties;
import cn.odboy.config.netty.ConfigCenterClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
/**
* 配置加载器
* @author odboy
* @date 2024-12-03
*/
@Slf4j
@Configuration
public class ConfigCenterConfigLoader {
private static final String OS_TYPE_WIN = "win";
private static final String OS_TYPE_MAC = "mac";
private static final String DEFAULT_PATH_WIN = "c:/data";
private static final String DEFAULT_PATH_MAC = "/home/admin/data";
private static final String DEFAULT_CONFIG_SERVER = "127.0.0.1";
private static final Integer DEFAULT_CONFIG_PORT = 28002;
private static final String DEFAULT_CONFIG_ENV = "default";
private static final String DEFAULT_CONFIG_DATA_ID = "default";
@Autowired
private ConfigCenterProperties properties;
@Bean
public BeanFactoryPostProcessor configLoader(ConfigurableEnvironment environment) {
return new BeanFactoryPostProcessor() {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String cacheDir;
String os = System.getProperty("os.name");
if (os.toLowerCase().startsWith(OS_TYPE_WIN)) {
cacheDir = DEFAULT_PATH_WIN;
} else if (os.toLowerCase().startsWith(OS_TYPE_MAC)) {
cacheDir = DEFAULT_PATH_MAC;
}else {
cacheDir = DEFAULT_PATH_MAC;
}
environment.getProperty("kenaito.config-center.server", String.class, DEFAULT_CONFIG_SERVER);
environment.getProperty("kenaito.config-center.port", Integer.class, DEFAULT_CONFIG_PORT);
environment.getProperty("kenaito.config-center.env", String.class, DEFAULT_CONFIG_ENV);
environment.getProperty("kenaito.config-center.data-id", String.class, DEFAULT_CONFIG_DATA_ID);
environment.getProperty("kenaito.config-center.cache-dir", String.class, cacheDir);
ConfigCenterClient client = new ConfigCenterClient();
try {
client.start(properties);
} catch (InterruptedException e) {
log.error("Netty Client Start Error", e);
throw new RuntimeException(e);
}
// ConfigCenterClient client = new ConfigCenterClient("http://your-config-center-url/config");
// Map<String, Object> configKv = client.fetchConfig();
// MapPropertySource propertySource = new MapPropertySource("configCenter", configKv);
// environment.getPropertySources().addFirst(propertySource);
}
};
}
}

View File

@ -0,0 +1,15 @@
package cn.odboy.config.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ConfigKv implements Serializable {
private String key;
private Object value;
}

View File

@ -0,0 +1,34 @@
package cn.odboy.config.netty;
import cn.odboy.config.ConfigCenterProperties;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ConfigCenterClient {
public void start(ConfigCenterProperties properties) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ConfigCenterClientHandler());
}
});
log.info("Netty Client Start...");
ChannelFuture channelFuture = bootstrap.connect(properties.getServer(), properties.getPort()).sync();
channelFuture.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}

View File

@ -0,0 +1,25 @@
package cn.odboy.config.netty;
import cn.odboy.config.model.ConfigKv;
import cn.odboy.config.util.ProtostuffUtil;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
public class ConfigCenterClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("收到服务器消息:" + msg);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("MyClientHandler发送数据");
//ctx.writeAndFlush("测试String编解码");
//测试对象编解码
//ctx.writeAndFlush(new User(1,"zhuge"));
//测试用protostuff对对象编解码
ByteBuf buf = Unpooled.copiedBuffer(ProtostuffUtil.serializer(new ConfigKv("app.config", "张三")));
ctx.writeAndFlush(buf);
}
}

View File

@ -0,0 +1,73 @@
package cn.odboy.config.util;
import cn.odboy.config.model.ConfigKv;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* protostuff 序列化工具类基于protobuf封装
*/
public class ProtostuffUtil {
private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>();
private static <T> Schema<T> getSchema(Class<T> clazz) {
@SuppressWarnings("unchecked")
Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);
if (schema == null) {
schema = RuntimeSchema.getSchema(clazz);
if (schema != null) {
cachedSchema.put(clazz, schema);
}
}
return schema;
}
/**
* 序列化
*
* @param obj
* @return
*/
public static <T> byte[] serializer(T obj) {
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema<T> schema = getSchema(clazz);
return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
}
/**
* 反序列化
*
* @param data
* @param clazz
* @return
*/
public static <T> T deserializer(byte[] data, Class<T> clazz) {
try {
T obj = clazz.newInstance();
Schema<T> schema = getSchema(clazz);
ProtostuffIOUtil.mergeFrom(data, obj, schema);
return obj;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
public static void main(String[] args) {
byte[] userBytes = ProtostuffUtil.serializer(new ConfigKv("app.config", "zhuge"));
ConfigKv user = ProtostuffUtil.deserializer(userBytes, ConfigKv.class);
System.out.println(user);
}
}

View File

@ -0,0 +1,58 @@
package cn.odboy.infra.netty;
import cn.hutool.core.thread.ThreadUtil;
import cn.odboy.config.ConfigCenterProperties;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ConfigNettyServer implements InitializingBean {
@Autowired
private ConfigCenterProperties properties;
@Override
public void afterPropertiesSet() throws Exception {
ThreadUtil.execAsync(() -> {
try {
start();
} catch (InterruptedException e) {
log.error("Netty Server Start Error", e);
throw new RuntimeException(e);
}
});
}
public void start() throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(2);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ConfigServerHandler());
}
});
log.info("Netty Server Start...");
ChannelFuture channelFuture = serverBootstrap.bind(properties.getPort()).sync();
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}

View File

@ -0,0 +1,26 @@
package cn.odboy.infra.netty;
import cn.odboy.config.model.ConfigKv;
import cn.odboy.config.util.ProtostuffUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class ConfigServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//System.out.println("从客户端读取到String" + msg.toString());
//System.out.println("从客户端读取到Object" + ((User)msg).toString());
//测试用protostuff对对象编解码
ByteBuf buf = (ByteBuf) msg;
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
System.out.println("从客户端读取到Object" + ProtostuffUtil.deserializer(bytes, ConfigKv.class));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

View File

@ -1,6 +1,7 @@
kenaito:
config-center:
meta: http://127.0.0.1:28002
server: 127.0.0.1
port: 28002
data-id: kenaito-config-service
cache-dir: /home/admin/data
env: daily

View File

@ -1,6 +1,7 @@
kenaito:
config-center:
meta: http://127.0.0.1:28000
server: 127.0.0.1
port: 28002
data-id: kenaito-config-service
cache-dir: /home/admin/data
env: production

View File

@ -1,6 +1,7 @@
kenaito:
config-center:
meta: http://127.0.0.1:28002
server: 127.0.0.1
port: 28002
data-id: kenaito-config-service
cache-dir: /home/admin/data
env: stage

View File

@ -1,4 +1,4 @@
spring:
profiles:
# 激活哪个配置文件, application-{active}.yml
active: dev
active: daily