Compare commits

...

10 Commits

Author SHA1 Message Date
Wxx
f7767c39d2 update 2025-03-08 22:22:18 +08:00
Wxx
788e860c65 update 2025-03-08 22:20:37 +08:00
Wxx
416cdad2dd update 2025-03-08 22:19:09 +08:00
Wxx
3c061abe43 step4:snowflake 2025-03-08 01:36:27 +08:00
Wxx
206a56c07e version6:step3-心跳检测优化 2025-03-01 21:22:59 +08:00
Wxx
9cf25a765d version6:step2-日志链路追踪实现 2025-02-27 18:45:06 +08:00
Wxx
bbe88333df fix 2025-02-27 16:21:48 +08:00
Wxx
337ef19a58 add 2025-02-13 17:12:40 +08:00
Wxx
83b49f0365 version6:step1-心跳检测 2025-02-13 16:39:06 +08:00
Wxx
f4f0a28179 fix:优雅关闭;单例序列化器 2025-02-12 16:37:47 +08:00
205 changed files with 4583 additions and 15 deletions

BIN
README.assets/version6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@ -293,8 +293,24 @@ D:\software\JDK17\bin\java -cp "target\krpc-consumer-1.0-SNAPSHOT.jar;target\lib
# 版本六
- 分布式日志链路追踪
- 心跳检测
- 基于方法白名单的重试
![](README.assets/version6.jpg)
# TodoList
- [ ] **数据传输压缩加密认证**
- [ ] 使用注解注册服务,消费服务
- [ ] 主动下线失败次数过多的节点

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="version1" />
</profile>
</annotationProcessing>
</component>
</project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
</component>
</project>

12
version1/.idea/misc.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="openjdk-17" project-jdk-type="JavaSDK" />
</project>

6
version1/.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="9965864c-cbac-4894-9fcb-93103359c7c9" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="MavenImportPreferences">
<option name="generalSettings">
<MavenGeneralSettings>
<option name="useMavenConfig" value="true" />
</MavenGeneralSettings>
</option>
</component>
<component name="ProjectId" id="2rZLqmF1kJPC1rsizHNhnfx35iF" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"WebServerToolWindowFactoryState": "false",
"last_opened_file_path": "E:/JAVA_coding/Rpc-New/RPC-Java/version1"
}
}]]></component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="9965864c-cbac-4894-9fcb-93103359c7c9" name="Changes" comment="" />
<created>1736761843999</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1736761843999</updated>
<workItem from="1736761845507" duration="6000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
</project>

8
version4/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="version4" />
</profile>
</annotationProcessing>
</component>
</project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
</component>
</project>

12
version4/.idea/misc.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="openjdk-17" project-jdk-type="JavaSDK" />
</project>

6
version4/.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@ -16,5 +16,10 @@
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
</component>
</project>

View File

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings" defaultProject="true" />
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@ -20,16 +20,19 @@ public interface Serializer {
int getType();
// 定义静态常量 serializerMap
static final Map<Integer, Serializer> serializerMap = new HashMap<>();
// 使用 Map 存储序列化器
static Serializer getSerializerByCode(int code) {
// 静态映射保证只初始化一次
Map<Integer, Serializer> serializerMap = new HashMap<>();
if(serializerMap.isEmpty()) {
serializerMap.put(0, new ObjectSerializer());
serializerMap.put(1, new JsonSerializer());
serializerMap.put(2, new KryoSerializer());
serializerMap.put(3, new HessianSerializer());
serializerMap.put(4, new ProtostuffSerializer());
}
return serializerMap.get(code); // 如果不存在则返回 null
}
}

View File

@ -61,6 +61,7 @@ public class ConsumerTest {
// Gracefully shutdown the executor service
executorService.shutdown();
clientProxy.close();
}
}

View File

@ -109,4 +109,11 @@ public class ClientProxy implements InvocationHandler {
}
return sb.toString();
}
//关闭创建的资源
//如果在需要C-S保持长连接的场景下无需调用close方法
public void close(){
rpcClient.close();
serviceCenter.close();
}
}

View File

@ -14,4 +14,5 @@ import common.message.RpcResponse;
public interface RpcClient {
RpcResponse sendRequest(RpcRequest request);
void close();
}

View File

@ -68,7 +68,6 @@ public class NettyRpcClient implements RpcClient {
// 其它场景也可以选择添加监听器的方式来异步获取结果 channelFuture.addListener...
AttributeKey<RpcResponse> key = AttributeKey.valueOf("RPCResponse");
RpcResponse response = channel.attr(key).get();
if (response == null) {
log.error("服务响应为空,可能是请求失败或超时");
return RpcResponse.fail("服务响应为空");
@ -82,14 +81,13 @@ public class NettyRpcClient implements RpcClient {
} catch (Exception e) {
log.error("发送请求时发生异常: {}", e.getMessage(), e);
} finally {
// 连接断开后优雅地关闭 Netty 资源
shutdown();
//
}
return RpcResponse.fail("请求失败");
}
// 优雅关闭 Netty 资源
private void shutdown() {
public void close() {
try {
if (eventLoopGroup != null) {
eventLoopGroup.shutdownGracefully().sync();

View File

@ -54,4 +54,9 @@ public class SimpleSocketRpcClient implements RpcClient {
return response;
}
@Override
public void close() {
}
}

View File

@ -19,4 +19,7 @@ public interface ServiceCenter {
//判断是否可重试
boolean checkRetry(InetSocketAddress serviceAddress, String methodSignature);
//关闭客户端
void close();
}

View File

@ -104,6 +104,11 @@ public class ZKServiceCenter implements ServiceCenter {
return retryServiceCache.contains(methodSignature);
}
@Override
public void close() {
client.close();
}
// 将InetSocketAddress解析为格式为ip:port的字符串
private String getServiceAddress(InetSocketAddress serverAddress){
return serverAddress.getHostName() + ":" + serverAddress.getPort();

View File

@ -20,13 +20,13 @@ public class RateLimitProvider {
private final Map<String, RateLimit> rateLimitMap = new ConcurrentHashMap<>();
// 默认的限流桶容量和令牌生成速率
private static final int DEFAULT_CAPACITY = 100;
private static final int DEFAULT_RATE = 10;
private static final int DEFAULT_CAPACITY = 10;
private static final int DEFAULT_RATE = 100;
// 提供限流实例
public RateLimit getRateLimit(String interfaceName) {
return rateLimitMap.computeIfAbsent(interfaceName, key -> {
RateLimit rateLimit = new TokenBucketRateLimitImpl(DEFAULT_CAPACITY, DEFAULT_RATE);
RateLimit rateLimit = new TokenBucketRateLimitImpl(DEFAULT_RATE, DEFAULT_CAPACITY);
log.info("为接口 [{}] 创建了新的限流策略: {}", interfaceName, rateLimit);
return rateLimit;
});

8
version6/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="krpc-core" />
<module name="krpc-common" />
<module name="krpc-provider" />
<module name="krpc-api" />
<module name="krpc-consumer" />
</profile>
</annotationProcessing>
</component>
</project>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/krpc-api/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-api/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-consumer/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-consumer/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-provider/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/krpc-provider/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
</component>
</project>

14
version6/.idea/misc.xml Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17 (2)" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

6
version6/.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

20
version6/krpc-api/pom.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>version6</artifactId>
<groupId>com.kama</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>krpc-api</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,13 @@
package com.kama.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Retryable {
}

View File

@ -0,0 +1,26 @@
package com.kama.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @ClassName User
* @Description User对象
* @Author Tong
* @LastChangeDate 2024-12-05 0:53
* @Version v5.0
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
// 客户端和服务端共有的
private Integer id;
private String userName;
private Boolean gender;
}

View File

@ -0,0 +1,24 @@
package com.kama.service;
import com.kama.annotation.Retryable;
import com.kama.pojo.User;
/**
* @InterfaceName UserService
* @Description 接口
* @Author Tong
* @LastChangeDate 2024-12-05 0:52
* @Version v1.0
*/
public interface UserService {
// 查询
@Retryable
User getUserByUserId(Integer id);
// 新增
@Retryable
Integer insertUserId(User user);
}

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>version6</artifactId>
<groupId>com.kama</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>krpc-common</artifactId>
<dependencies>
<dependency>
<groupId>com.kama</groupId>
<artifactId>krpc-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
<scope>compile</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,17 @@
package common.exception;
/**
* @ClassName SerializeException
* @Description ToDo
* @Author Tong
* @LastChangeDate 2024-12-02 19:18
* @Version v1.0
*/
public class SerializeException extends RuntimeException{
public SerializeException(String message) {
super(message);
}
public SerializeException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,13 @@
package common.message;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public enum MessageType {
REQUEST(0), RESPONSE(1);
private int code;
public int getCode() {
return code;
}
}

View File

@ -0,0 +1,18 @@
package common.message;
import lombok.AllArgsConstructor;
/**
* @author wxx
* @version 1.0
* @create 2025/2/28 18:32
*/
@AllArgsConstructor
public enum RequestType {
NORMAL(0), HEARTBEAT(1);
private int code;
public int getCode() {
return code;
}
}

View File

@ -0,0 +1,37 @@
package common.message;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @ClassName RpcRequest
* @Description 定义请求消息格式
* @Author Tong
* @LastChangeDate 2024-11-29 10:12
* @Version v5.0
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class RpcRequest implements Serializable {
//v6新增:请求类型
private RequestType type=RequestType.NORMAL;
//接口名方法名参数列表参数类型
private String interfaceName;
private String methodName;
private Object[] params;
private Class<?>[] paramsType;
public static RpcRequest heartBeat() {
return RpcRequest.builder().type(RequestType.HEARTBEAT).build();
}
}

View File

@ -0,0 +1,37 @@
package common.message;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @ClassName RpcResponse
* @Description 定义响应消息格式
* @Author Tong
* @LastChangeDate 2024-11-29 10:14
* @Version v5.0
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class RpcResponse implements Serializable {
//状态信息
private int code;
private String message;
//更新加入传输数据的类型以便在自定义序列化器中解析
private Class<?> dataType;
//具体数据
private Object data;
public static RpcResponse sussess(Object data) {
return RpcResponse.builder().code(200).dataType(data.getClass()).data(data).build();
}
public static RpcResponse fail(String msg) {
return RpcResponse.builder().code(500).message(msg).build();
}
}

View File

@ -0,0 +1,72 @@
package common.serializer.mycoder;
import common.exception.SerializeException;
import common.message.MessageType;
import common.serializer.myserializer.Serializer;
import common.trace.TraceContext;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import java.util.Arrays;
import java.util.List;
/**
* @ClassName MyDecoder
* @Description 解码器
* @Author Tong
* @LastChangeDate 2024-11-29 10:32
* @Version v5.0
*/
@Slf4j
public class MyDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out) throws Exception {
//检查可读字节数
if (in.readableBytes() < 6) { // messageType + serializerType + length
return;
}
//1.读取traceMsg
int traceLength=in.readInt();
byte[] traceBytes=new byte[traceLength];
in.readBytes(traceBytes);
serializeTraceMsg(traceBytes);
//2.读取消息类型
short messageType = in.readShort();
// 现在还只支持request与response请求
if (messageType != MessageType.REQUEST.getCode() &&
messageType != MessageType.RESPONSE.getCode()) {
log.warn("暂不支持此种数据, messageType: {}", messageType);
return;
}
//3.读取序列化的方式&类型
short serializerType = in.readShort();
Serializer serializer = Serializer.getSerializerByCode(serializerType);
if (serializer == null) {
log.error("不存在对应的序列化器, serializerType: {}", serializerType);
throw new SerializeException("不存在对应的序列化器, serializerType: " + serializerType);
}
//4.读取序列化数组长度
int length = in.readInt();
if (in.readableBytes() < length) {
return; // 数据不完整等待更多数据
}
//5.读取序列化数组
byte[] bytes = new byte[length];
in.readBytes(bytes);
log.debug("Received bytes: {}", Arrays.toString(bytes));
Object deserialize = serializer.deserialize(bytes, messageType);
out.add(deserialize);
}
//解析并存储traceMsg
private void serializeTraceMsg(byte[] traceByte){
String traceMsg=new String(traceByte);
String[] msgs=traceMsg.split(";");
if(!msgs[0].equals("")) TraceContext.setTraceId(msgs[0]);
if(!msgs[1].equals("")) TraceContext.setParentSpanId(msgs[1]);
}
}

View File

@ -0,0 +1,60 @@
package common.serializer.mycoder;
import common.message.MessageType;
import common.message.RpcRequest;
import common.message.RpcResponse;
import common.serializer.myserializer.Serializer;
import common.trace.TraceContext;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
/**
* @ClassName MyEncoder
* @Description 编码器
* @Author Tong
* @LastChangeDate 2024-11-29 10:32
* @Version v5.0
*/
@Slf4j
@AllArgsConstructor
public class MyEncoder extends MessageToByteEncoder {
private Serializer serializer;
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
log.debug("Encoding message of type: {}", msg.getClass());
//1.写入trace消息头
String traceMsg= TraceContext.getTraceId() +";"+TraceContext.getSpanId();
byte[] traceBytes=traceMsg.getBytes();
// 1.1写入traceMsg长度
out.writeInt(traceBytes.length);
// 1.2写入traceBytes
out.writeBytes(traceBytes);
//2.写入消息类型
if (msg instanceof RpcRequest) {
out.writeShort(MessageType.REQUEST.getCode());
} else if (msg instanceof RpcResponse) {
out.writeShort(MessageType.RESPONSE.getCode());
} else {
log.error("Unknown message type: {}", msg.getClass());
throw new IllegalArgumentException("Unknown message type: " + msg.getClass());
}
//3.写入序列化方式
out.writeShort(serializer.getType());
//得到序列化数组
byte[] serializeBytes = serializer.serialize(msg);
if (serializeBytes == null || serializeBytes.length == 0) {
throw new IllegalArgumentException("Serialized message is empty");
}
//4.写入长度
out.writeInt(serializeBytes.length);
//5.写入序列化数组
out.writeBytes(serializeBytes);
}
}

View File

@ -0,0 +1,51 @@
package common.serializer.myserializer;
import com.caucho.hessian.io.HessianInput;
import com.caucho.hessian.io.HessianOutput;
import common.exception.SerializeException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* @ClassName HessianSerializer
* @Description Hessian序列化
* @Author Tong
* @LastChangeDate 2024-11-29 11:49
* @Version v5.0
*/
public class HessianSerializer implements Serializer {
@Override
public byte[] serialize(Object obj) {
// 使用 ByteArrayOutputStream HessianOutput 来实现对象的序列化
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
HessianOutput hessianOutput = new HessianOutput(byteArrayOutputStream);
hessianOutput.writeObject(obj); // 将对象写入输出流
return byteArrayOutputStream.toByteArray(); // 返回字节数组
} catch (IOException e) {
throw new SerializeException("Serialization failed");
}
}
@Override
public Object deserialize(byte[] bytes, int messageType) {
// 使用 ByteArrayInputStream HessianInput 来实现反序列化
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)) {
HessianInput hessianInput = new HessianInput(byteArrayInputStream);
return hessianInput.readObject(); // 读取并返回对象
} catch (IOException e) {
throw new SerializeException("Deserialization failed");
}
}
@Override
public int getType() {
return 3;
}
@Override
public String toString() {
return "Hessian";
}
}

View File

@ -0,0 +1,78 @@
package common.serializer.myserializer;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import common.message.RpcRequest;
import common.message.RpcResponse;
/**
* @ClassName JsonSerializer
* @Description json序列化
* @Author Tong
* @LastChangeDate 2024-11-29 10:33
* @Version v5.0
*/
public class JsonSerializer implements Serializer {
@Override
public byte[] serialize(Object obj) {
byte[] bytes = JSONObject.toJSONBytes(obj);
return bytes;
}
@Override
public Object deserialize(byte[] bytes, int messageType) {
Object obj = null;
// 传输的消息分为request与response
switch (messageType){
case 0:
RpcRequest request = JSON.parseObject(bytes, RpcRequest.class);
Object[] objects = new Object[request.getParams().length];
// 把json字串转化成对应的对象 fastjson可以读出基本数据类型不用转化
// 对转换后的request中的params属性逐个进行类型判断
for(int i = 0; i < objects.length; i++){
Class<?> paramsType = request.getParamsType()[i];
//判断每个对象类型是否和paramsTypes中的一致
if (!paramsType.isAssignableFrom(request.getParams()[i].getClass())){
//如果不一致就行进行类型转换
objects[i] = JSONObject.toJavaObject((JSONObject) request.getParams()[i],request.getParamsType()[i]);
}else{
//如果一致就直接赋给objects[i]
objects[i] = request.getParams()[i];
}
}
request.setParams(objects);
obj = request;
break;
case 1:
RpcResponse response = JSON.parseObject(bytes, RpcResponse.class);
// 如果类型为空说明返回错误
if(response.getDataType()==null){
obj = RpcResponse.fail("类型为空");
break;
}
Class<?> dataType = response.getDataType();
//判断转化后的response对象中的data的类型是否正确
if(response.getData() != null && !dataType.isAssignableFrom(response.getData().getClass())){
response.setData(JSONObject.toJavaObject((JSONObject) response.getData(),dataType));
}
obj = response;
break;
default:
System.out.println("暂时不支持此种消息");
throw new RuntimeException();
}
return obj;
}
//1 代表json序列化方式
@Override
public int getType() {
return 1;
}
@Override
public String toString() {
return "Json";
}
}

View File

@ -0,0 +1,80 @@
package common.serializer.myserializer;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.kama.pojo.User;
import common.exception.SerializeException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
/**
* @ClassName KryoSerializer
* @Description kryo序列化
* @Author Tong
* @LastChangeDate 2024-11-29 11:29
* @Version v5.0
*/
public class KryoSerializer implements Serializer {
private Kryo kryo;
public KryoSerializer() {
this.kryo = new Kryo();
}
@Override
public byte[] serialize(Object obj) {
if (obj == null) {
throw new IllegalArgumentException("Cannot serialize null object");
}
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Output output = new Output(byteArrayOutputStream)) {
kryo.writeObject(output, obj); // 使用 Kryo 写入对象
return output.toBytes(); // 返回字节数组
} catch (Exception e) {
throw new SerializeException("Serialization failed");
}
}
@Override
public Object deserialize(byte[] bytes, int messageType) {
if (bytes == null || bytes.length == 0) {
throw new IllegalArgumentException("Cannot deserialize null or empty byte array");
}
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
Input input = new Input(byteArrayInputStream)) {
// 根据 messageType 来反序列化不同的类
Class<?> clazz = getClassForMessageType(messageType);
return kryo.readObject(input, clazz); // 使用 Kryo 反序列化对象
} catch (Exception e) {
throw new SerializeException("Deserialization failed");
}
}
@Override
public int getType() {
return 2;
}
private Class<?> getClassForMessageType(int messageType) {
if (messageType == 1) {
return User.class; // 假设我们在此反序列化成 User
} else {
throw new SerializeException("Unknown message type: " + messageType);
}
}
@Override
public String toString() {
return "Kryo";
}
}

View File

@ -0,0 +1,60 @@
package common.serializer.myserializer;
import java.io.*;
/**
* @ClassName ObjectSerializer
* @Description JDK序列化方式
* @Author Tong
* @LastChangeDate 2024-11-29 10:34
* @Version v5.0
*/
public class ObjectSerializer implements Serializer {
//利用Java io 对象 -字节数组
@Override
public byte[] serialize(Object obj) {
byte[] bytes=null;
ByteArrayOutputStream bos=new ByteArrayOutputStream();
try {
//是一个对象输出流用于将 Java 对象序列化为字节流并将其连接到bos上
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
//刷新 ObjectOutputStream确保所有缓冲区中的数据都被写入到底层流中
oos.flush();
//将bos其内部缓冲区中的数据转换为字节数组
bytes = bos.toByteArray();
oos.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
//字节数组 -对象
@Override
public Object deserialize(byte[] bytes, int messageType) {
Object obj = null;
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
try {
ObjectInputStream ois = new ObjectInputStream(bis);
obj = ois.readObject();
ois.close();
bis.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return obj;
}
//0 代表Java 原生序列器
@Override
public int getType() {
return 0;
}
@Override
public String toString() {
return "JDK";
}
}

View File

@ -0,0 +1,83 @@
package common.serializer.myserializer;
import com.kama.pojo.User;
import common.exception.SerializeException;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
/**
* @ClassName ProtostuffSerializer
* @Description protostuff序列化
* @Author Tong
* @LastChangeDate 2024-11-29 11:55
* @Version v5.0
*/
public class ProtostuffSerializer implements Serializer {
@Override
public byte[] serialize(Object obj) {
// 检查 null 对象
if (obj == null) {
throw new IllegalArgumentException("Cannot serialize null object");
}
// 获取对象的 schema
Schema schema = RuntimeSchema.getSchema(obj.getClass());
// 使用 LinkedBuffer 来创建缓冲区默认大小 1024
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
// 序列化对象为字节数组
byte[] bytes;
try {
bytes = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} finally {
buffer.clear();
}
return bytes;
}
@Override
public Object deserialize(byte[] bytes, int messageType) {
if (bytes == null || bytes.length == 0) {
throw new IllegalArgumentException("Cannot deserialize null or empty byte array");
}
// 根据 messageType 来决定反序列化的类这里假设 `messageType` 是类的标识符
Class<?> clazz = getClassForMessageType(messageType);
// 获取对象的 schema
Schema schema = RuntimeSchema.getSchema(clazz);
// 创建一个空的对象实例
Object obj;
try {
obj = clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new SerializeException("Deserialization failed due to reflection issues");
}
// 反序列化字节数组为对象
ProtostuffIOUtil.mergeFrom(bytes, obj, schema);
return obj;
}
@Override
public int getType() {
return 4;
}
// 用于根据 messageType 获取对应的类
private Class<?> getClassForMessageType(int messageType) {
if (messageType == 1) {
return User.class; // 假设我们在此反序列化成 User
} else {
throw new SerializeException("Unknown message type: " + messageType);
}
}
@Override
public String toString() {
return "Protostuff";
}
}

View File

@ -0,0 +1,38 @@
package common.serializer.myserializer;
import java.util.HashMap;
import java.util.Map;
/**
* @InterfaceName Serializer
* @Description 序列化接口
* @Author Tong
* @LastChangeDate 2024-11-29 10:33
* @Version v5.0
*/
public interface Serializer {
byte[] serialize(Object obj);
Object deserialize(byte[] bytes, int messageType);
int getType();
// 定义静态常量 serializerMap
static final Map<Integer, Serializer> serializerMap = new HashMap<>();
// 使用 Map 存储序列化器
static Serializer getSerializerByCode(int code) {
// 静态映射保证只初始化一次
if(serializerMap.isEmpty()) {
serializerMap.put(0, new ObjectSerializer());
serializerMap.put(1, new JsonSerializer());
serializerMap.put(2, new KryoSerializer());
serializerMap.put(3, new HessianSerializer());
serializerMap.put(4, new ProtostuffSerializer());
}
return serializerMap.get(code); // 如果不存在则返回 null
}
}

View File

@ -0,0 +1,111 @@
package common.spi;
import cn.hutool.core.io.resource.ResourceUtil;
import common.serializer.myserializer.Serializer;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @ClassName SpiLoader
* @Description spi实现
* @Author Tong
* @LastChangeDate 2024-12-05 14:53
* @Version v5.0
*/
@Slf4j
public class SpiLoader {
// 存储已加载的 SPI 实现类的映射
private static final Map<String, Map<String, Class<? extends Serializer>>> loadedSpiMap = new ConcurrentHashMap<>();
// 缓存实例避免重复实例化
private static final Map<String, Object> instanceCache = new ConcurrentHashMap<>();
// SPI 配置文件的路径
private static final String SPI_CONFIG_DIR = "META-INF/serializer/";
/**
* 加载指定接口的 SPI 实现类
*
* @param serviceInterface 接口类
*/
public static void loadSpi(Class<?> serviceInterface) {
String interfaceName = serviceInterface.getName();
// 如果已经加载过该接口的 SPI 实现直接返回
if (loadedSpiMap.containsKey(interfaceName)) {
return;
}
Map<String, Class<? extends Serializer>> keyClassMap = new HashMap<>();
// 读取配置文件获取所有实现类
List<URL> resources = ResourceUtil.getResources(SPI_CONFIG_DIR + serviceInterface.getName());
for (URL resource : resources) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream()))) {
String line;
while ((line = reader.readLine()) != null) {
if (!line.trim().isEmpty() && !line.startsWith("#")) {
String[] parts = line.split("=");
if (parts.length == 2) {
String key = parts[0].trim();
String className = parts[1].trim();
Class<?> implClass = Class.forName(className);
if (serviceInterface.isAssignableFrom(implClass)) {
keyClassMap.put(key, (Class<? extends Serializer>) implClass);
}
}
}
}
} catch (IOException | ClassNotFoundException e) {
log.error("Failed to load SPI resource: " + resource, e);
}
}
// 将该接口的 SPI 实现类存入缓存
loadedSpiMap.put(interfaceName, keyClassMap);
}
/**
* 根据接口和 key 获取 SPI 实现类实例
*
* @param serviceInterface 接口类
* @param key 序列化器的 key
* @param <T> 接口类型
* @return 对应的 SPI 实现类实例
*/
public static <T> T getInstance(Class<T> serviceInterface, String key) {
String interfaceName = serviceInterface.getName();
Map<String, Class<? extends Serializer>> keyClassMap = loadedSpiMap.get(interfaceName);
if (keyClassMap == null) {
throw new RuntimeException("SPI not loaded for " + interfaceName);
}
Class<? extends Serializer> implClass = keyClassMap.get(key);
if (implClass == null) {
throw new RuntimeException("No SPI implementation found for key " + key);
}
// 从缓存中获取实例如果不存在则创建
String implClassName = implClass.getName();
if (!instanceCache.containsKey(implClassName)) {
try {
instanceCache.put(implClassName, implClass.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("Failed to instantiate SPI implementation: " + implClassName, e);
}
}
return (T) instanceCache.get(implClassName);
}
}

View File

@ -0,0 +1,56 @@
package common.trace;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import java.util.Map;
/**
* @author wxx
* @version 1.0
* @create 2025/2/18 18:37
*/
@Slf4j
public class TraceContext {
public static void setTraceId(String traceId) {
MDC.put("traceId",traceId);
}
public static String getTraceId() {
return MDC.get("traceId");
}
public static void setSpanId(String spanId) {
MDC.put("spanId",spanId);
}
public static String getSpanId() {
return MDC.get("spanId");
}
public static void setParentSpanId(String parentSpanId) {
MDC.put("parentSpanId",parentSpanId);
}
public static String getParentSpanId() {
return MDC.get("parentSpanId");
}
public static void setStartTimestamp(String startTimestamp) {
MDC.put("startTimestamp",startTimestamp);
}
public static String getStartTimestamp() {
return MDC.get("startTimestamp");
}
public static Map<String,String> getCopy(){
return MDC.getCopyOfContextMap();
}
public static void clone(Map<String,String> context){
for(Map.Entry<String,String> entry:context.entrySet()){
MDC.put(entry.getKey(),entry.getValue());
}
}
public static void clear() {
MDC.clear();
}
}

View File

@ -0,0 +1,48 @@
package common.util;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import lombok.extern.slf4j.Slf4j;
/**
* @ClassName ConfigUtil
* @Description 工具
* @Author Tong
* @LastChangeDate 2024-12-05 11:12
* @Version v5.0
*/
@Slf4j
public class ConfigUtil {
// 加载配置文件使用默认环境
public static <T> T loadConfig(Class<T> targetClass, String prefix) {
return loadConfig(targetClass, prefix, "");
}
// 加载配置文件支持指定环境
public static <T> T loadConfig(Class<T> targetClass, String prefix, String environment) {
StringBuilder configFileNameBuilder = new StringBuilder("application");
if (StrUtil.isNotBlank(environment)) {
configFileNameBuilder.append("-").append(environment);
}
configFileNameBuilder.append(".properties");
// 加载配置文件
Props properties = new Props(configFileNameBuilder.toString());
if (properties.isEmpty()) {
log.warn("配置文件 '{}' 为空或加载失败!", configFileNameBuilder.toString());
} else {
log.info("加载配置文件: '{}'", configFileNameBuilder.toString());
}
// 返回转化后的配置对象
try {
return properties.toBean(targetClass, prefix);
} catch (Exception e) {
log.error("配置转换失败,目标类: {}", targetClass.getName(), e);
throw new RuntimeException("配置加载失败", e);
}
}
}

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>version6</artifactId>
<groupId>com.kama</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>krpc-consumer</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.kama</groupId>
<artifactId>krpc-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.kama</groupId>
<artifactId>krpc-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.kama</groupId>
<artifactId>krpc-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,66 @@
package com.kama.consumer;
import com.kama.client.proxy.ClientProxy;
import com.kama.pojo.User;
import com.kama.service.UserService;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @ClassName ConsumerExample
* @Description 客户端测试
* @Author Tong
* @LastChangeDate 2024-12-05 16:20
* @Version v5.0
*/
@Slf4j
public class ConsumerTest {
private static final int THREAD_POOL_SIZE = 30;
private static final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
public static void main(String[] args) throws InterruptedException {
ClientProxy clientProxy = new ClientProxy();
UserService proxy = clientProxy.getProxy(UserService.class);
for (int i = 0; i < 120; i++) {
final Integer i1 = i;
if (i % 30 == 0) {
// Simulate delay for every 30 requests
Thread.sleep(10000);
}
// Submit tasks to executor service (thread pool)
executorService.submit(() -> {
try {
User user = proxy.getUserByUserId(i1);
if (user != null) {
log.info("从服务端得到的user={}", user);
} else {
log.warn("获取的 user 为 null, userId={}", i1);
}
Integer id = proxy.insertUserId(User.builder()
.id(i1)
.userName("User" + i1)
.gender(true)
.build());
if (id != null) {
log.info("向服务端插入user的id={}", id);
} else {
log.warn("插入失败返回的id为null, userId={}", i1);
}
} catch (Exception e) {
log.error("调用服务时发生异常userId={}", i1, e);
}
});
}
// Gracefully shutdown the executor service
executorService.shutdown();
clientProxy.close();
}
}

View File

@ -0,0 +1,20 @@
package com.kama.consumer;
import com.kama.config.KRpcConfig;
import common.util.ConfigUtil;
/**
* @ClassName ConsumerTestConfig
* @Description 测试配置顶
* @Author Tong
* @LastChangeDate 2024-12-05 11:29
* @Version v1.0
*/
public class ConsumerTestConfig {
public static void main(String[] args) {
KRpcConfig rpc = ConfigUtil.loadConfig(KRpcConfig.class, "rpc");
System.out.println(rpc);
}
}

View File

@ -0,0 +1,7 @@
rpc.name=krpc
rpc.version=1.0.0
rpc.port=9999
rpc.serializer=Hessian
rpc.host=localhost
rpc.registry=zookeeper
rpc.loadBalance=ConsistencyHash

View File

@ -0,0 +1,7 @@
rpc.name=krpc
rpc.version=1.0.0
rpc.port=9999
rpc.serializer=Hessian
rpc.host=localhost
rpc.registry=zookeeper
rpc.loadBalance=ConsistencyHash

130
version6/krpc-core/pom.xml Normal file
View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>version6</artifactId>
<groupId>com.kama</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>krpc-core</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.kama</groupId>
<artifactId>krpc-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.51.Final</version>
<scope>compile</scope>
</dependency>
<!--这个jar包应该依赖log4j,不引入log4j会有控制台会有warn但不影响正常使用-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.66</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>com.github.rholder</groupId>
<artifactId>guava-retrying</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>17.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.kama</groupId>
<artifactId>krpc-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
<!-- JUnit 5 API 和 Engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.3</version>
<scope>test</scope>
</dependency>
<!-- JUnit Platform Launcher -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.11.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.zipkin2</groupId>
<artifactId>zipkin</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,48 @@
package com.kama;
import com.kama.config.KRpcConfig;
import com.kama.config.RpcConstant;
import common.util.ConfigUtil;
import lombok.extern.slf4j.Slf4j;
/**
* @ClassName RpcApplication
* @Description 测试配置顶学习更多参考Dubbo
* @Author Tong
* @LastChangeDate 2024-12-05 11:22
* @Version v5.0
*/
@Slf4j
public class KRpcApplication {
private static volatile KRpcConfig rpcConfigInstance;
public static void initialize(KRpcConfig customRpcConfig) {
rpcConfigInstance = customRpcConfig;
log.info("RPC 框架初始化,配置 = {}", customRpcConfig);
}
public static void initialize() {
KRpcConfig customRpcConfig;
try {
customRpcConfig = ConfigUtil.loadConfig(KRpcConfig.class, RpcConstant.CONFIG_FILE_PREFIX);
log.info("成功加载配置文件,配置文件名称 = {}", RpcConstant.CONFIG_FILE_PREFIX); // 添加成功加载的日志
} catch (Exception e) {
// 配置加载失败使用默认配置
customRpcConfig = new KRpcConfig();
log.warn("配置加载失败,使用默认配置");
}
initialize(customRpcConfig);
}
public static KRpcConfig getRpcConfig() {
if (rpcConfigInstance == null) {
synchronized (KRpcApplication.class) {
if (rpcConfigInstance == null) {
initialize(); // 确保在第一次调用时初始化
}
}
}
return rpcConfigInstance;
}
}

Some files were not shown because too many files have changed in this diff Show More