From 06ebd5c664c780c51b4bca3afa5d32af17951a91 Mon Sep 17 00:00:00 2001 From: odboy Date: Tue, 3 Dec 2024 21:49:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=85=8D=E7=BD=AE=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kenaito-config-core/pom.xml | 32 +++++++- .../cn/odboy/config/ConfigCenterClient.java | 26 ------- .../config/ConfigCenterConfigLoader.java | 30 -------- .../odboy/config/ConfigCenterProperties.java | 3 +- .../context/ConfigCenterConfigLoader.java | 66 +++++++++++++++++ .../java/cn/odboy/config/model/ConfigKv.java | 15 ++++ .../config/netty/ConfigCenterClient.java | 34 +++++++++ .../netty/ConfigCenterClientHandler.java | 25 +++++++ .../cn/odboy/config/util/ProtostuffUtil.java | 73 +++++++++++++++++++ .../odboy/infra/netty/ConfigNettyServer.java | 58 +++++++++++++++ .../infra/netty/ConfigServerHandler.java | 26 +++++++ .../resources/config/application-daily.yml | 3 +- .../config/application-production.yml | 3 +- .../resources/config/application-stage.yml | 3 +- .../src/main/resources/config/application.yml | 2 +- 15 files changed, 337 insertions(+), 62 deletions(-) delete mode 100644 kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterClient.java delete mode 100644 kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterConfigLoader.java create mode 100644 kenaito-config-core/src/main/java/cn/odboy/config/context/ConfigCenterConfigLoader.java create mode 100644 kenaito-config-core/src/main/java/cn/odboy/config/model/ConfigKv.java create mode 100644 kenaito-config-core/src/main/java/cn/odboy/config/netty/ConfigCenterClient.java create mode 100644 kenaito-config-core/src/main/java/cn/odboy/config/netty/ConfigCenterClientHandler.java create mode 100644 kenaito-config-core/src/main/java/cn/odboy/config/util/ProtostuffUtil.java create mode 100644 kenaito-config-service/src/main/java/cn/odboy/infra/netty/ConfigNettyServer.java create mode 100644 kenaito-config-service/src/main/java/cn/odboy/infra/netty/ConfigServerHandler.java diff --git a/kenaito-config-core/pom.xml b/kenaito-config-core/pom.xml index c4afeb3..db9d21c 100644 --- a/kenaito-config-core/pom.xml +++ b/kenaito-config-core/pom.xml @@ -9,13 +9,43 @@ 4.0.0 + 4.1.115.Final + 1.3.0 5.8.33 - 1.10 kenaito-config-core 子模块-配置中心sdk + + io.netty + netty-all + ${netty.version} + + + + + com.dyuproject.protostuff + protostuff-api + ${protostuff.version} + + + com.dyuproject.protostuff + protostuff-core + ${protostuff.version} + + + com.dyuproject.protostuff + protostuff-runtime + ${protostuff.version} + + + + + cn.hutool + hutool-all + ${hutool.version} + diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterClient.java b/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterClient.java deleted file mode 100644 index 6844d98..0000000 --- a/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterClient.java +++ /dev/null @@ -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 fetchConfig() { - ResponseEntity response = restTemplate.getForEntity(configCenterUrl, Map.class); - if (response.getStatusCode().is2xxSuccessful()) { - return response.getBody(); - } else { - throw new RuntimeException("Failed to fetch config from config center"); - } - } -} diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterConfigLoader.java b/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterConfigLoader.java deleted file mode 100644 index dc92e8a..0000000 --- a/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterConfigLoader.java +++ /dev/null @@ -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 configKv = client.fetchConfig(); -// MapPropertySource propertySource = new MapPropertySource("configCenter", configKv); -// environment.getPropertySources().addFirst(propertySource); - } - }; - } -} diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterProperties.java b/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterProperties.java index 9a7620b..ea3547f 100644 --- a/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterProperties.java +++ b/kenaito-config-core/src/main/java/cn/odboy/config/ConfigCenterProperties.java @@ -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; diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/context/ConfigCenterConfigLoader.java b/kenaito-config-core/src/main/java/cn/odboy/config/context/ConfigCenterConfigLoader.java new file mode 100644 index 0000000..18f3ab4 --- /dev/null +++ b/kenaito-config-core/src/main/java/cn/odboy/config/context/ConfigCenterConfigLoader.java @@ -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 configKv = client.fetchConfig(); +// MapPropertySource propertySource = new MapPropertySource("configCenter", configKv); +// environment.getPropertySources().addFirst(propertySource); + } + }; + } +} diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/model/ConfigKv.java b/kenaito-config-core/src/main/java/cn/odboy/config/model/ConfigKv.java new file mode 100644 index 0000000..74bd139 --- /dev/null +++ b/kenaito-config-core/src/main/java/cn/odboy/config/model/ConfigKv.java @@ -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; +} diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/netty/ConfigCenterClient.java b/kenaito-config-core/src/main/java/cn/odboy/config/netty/ConfigCenterClient.java new file mode 100644 index 0000000..15d7f4e --- /dev/null +++ b/kenaito-config-core/src/main/java/cn/odboy/config/netty/ConfigCenterClient.java @@ -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() { + @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(); + } + } +} diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/netty/ConfigCenterClientHandler.java b/kenaito-config-core/src/main/java/cn/odboy/config/netty/ConfigCenterClientHandler.java new file mode 100644 index 0000000..121a05d --- /dev/null +++ b/kenaito-config-core/src/main/java/cn/odboy/config/netty/ConfigCenterClientHandler.java @@ -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); + } +} diff --git a/kenaito-config-core/src/main/java/cn/odboy/config/util/ProtostuffUtil.java b/kenaito-config-core/src/main/java/cn/odboy/config/util/ProtostuffUtil.java new file mode 100644 index 0000000..212214c --- /dev/null +++ b/kenaito-config-core/src/main/java/cn/odboy/config/util/ProtostuffUtil.java @@ -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, Schema> cachedSchema = new ConcurrentHashMap, Schema>(); + + private static Schema getSchema(Class clazz) { + @SuppressWarnings("unchecked") + Schema schema = (Schema) cachedSchema.get(clazz); + if (schema == null) { + schema = RuntimeSchema.getSchema(clazz); + if (schema != null) { + cachedSchema.put(clazz, schema); + } + } + return schema; + } + + /** + * 序列化 + * + * @param obj + * @return + */ + public static byte[] serializer(T obj) { + @SuppressWarnings("unchecked") + Class clazz = (Class) obj.getClass(); + LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); + try { + Schema 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 deserializer(byte[] data, Class clazz) { + try { + T obj = clazz.newInstance(); + Schema 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); + } +} \ No newline at end of file diff --git a/kenaito-config-service/src/main/java/cn/odboy/infra/netty/ConfigNettyServer.java b/kenaito-config-service/src/main/java/cn/odboy/infra/netty/ConfigNettyServer.java new file mode 100644 index 0000000..5f1aba1 --- /dev/null +++ b/kenaito-config-service/src/main/java/cn/odboy/infra/netty/ConfigNettyServer.java @@ -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() { + @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(); + } + } +} diff --git a/kenaito-config-service/src/main/java/cn/odboy/infra/netty/ConfigServerHandler.java b/kenaito-config-service/src/main/java/cn/odboy/infra/netty/ConfigServerHandler.java new file mode 100644 index 0000000..8c5ec83 --- /dev/null +++ b/kenaito-config-service/src/main/java/cn/odboy/infra/netty/ConfigServerHandler.java @@ -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(); + } +} diff --git a/kenaito-config-service/src/main/resources/config/application-daily.yml b/kenaito-config-service/src/main/resources/config/application-daily.yml index 95b9f52..4df9266 100644 --- a/kenaito-config-service/src/main/resources/config/application-daily.yml +++ b/kenaito-config-service/src/main/resources/config/application-daily.yml @@ -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 \ No newline at end of file diff --git a/kenaito-config-service/src/main/resources/config/application-production.yml b/kenaito-config-service/src/main/resources/config/application-production.yml index ab32f0b..f287a61 100644 --- a/kenaito-config-service/src/main/resources/config/application-production.yml +++ b/kenaito-config-service/src/main/resources/config/application-production.yml @@ -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 \ No newline at end of file diff --git a/kenaito-config-service/src/main/resources/config/application-stage.yml b/kenaito-config-service/src/main/resources/config/application-stage.yml index 03cd802..27d1273 100644 --- a/kenaito-config-service/src/main/resources/config/application-stage.yml +++ b/kenaito-config-service/src/main/resources/config/application-stage.yml @@ -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 \ No newline at end of file diff --git a/kenaito-config-service/src/main/resources/config/application.yml b/kenaito-config-service/src/main/resources/config/application.yml index cc7425d..7a1ea5c 100644 --- a/kenaito-config-service/src/main/resources/config/application.yml +++ b/kenaito-config-service/src/main/resources/config/application.yml @@ -1,4 +1,4 @@ spring: profiles: # 激活哪个配置文件, application-{active}.yml - active: dev + active: daily