Compare commits
10 Commits
70f076867c
...
f7767c39d2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7767c39d2 | ||
|
|
788e860c65 | ||
|
|
416cdad2dd | ||
|
|
3c061abe43 | ||
|
|
206a56c07e | ||
|
|
9cf25a765d | ||
|
|
bbe88333df | ||
|
|
337ef19a58 | ||
|
|
83b49f0365 | ||
|
|
f4f0a28179 |
BIN
README.assets/version6.jpg
Normal file
BIN
README.assets/version6.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
16
README.md
16
README.md
@ -293,8 +293,24 @@ D:\software\JDK17\bin\java -cp "target\krpc-consumer-1.0-SNAPSHOT.jar;target\lib
|
||||
|
||||
|
||||
|
||||
# 版本六
|
||||
|
||||
- 分布式日志链路追踪
|
||||
- 心跳检测
|
||||
- 基于方法白名单的重试
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# TodoList
|
||||
|
||||
- [ ] **数据传输压缩加密认证**
|
||||
|
||||
- [ ] 使用注解注册服务,消费服务
|
||||
|
||||
- [ ] 主动下线失败次数过多的节点
|
||||
|
||||
13
version1/.idea/compiler.xml
Normal file
13
version1/.idea/compiler.xml
Normal 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>
|
||||
7
version1/.idea/encodings.xml
Normal file
7
version1/.idea/encodings.xml
Normal 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>
|
||||
20
version1/.idea/jarRepositories.xml
Normal file
20
version1/.idea/jarRepositories.xml
Normal 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
12
version1/.idea/misc.xml
Normal 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
6
version1/.idea/vcs.xml
Normal 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>
|
||||
62
version1/.idea/workspace.xml
Normal file
62
version1/.idea/workspace.xml
Normal 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
8
version4/.idea/.gitignore
vendored
Normal 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
|
||||
13
version4/.idea/compiler.xml
Normal file
13
version4/.idea/compiler.xml
Normal 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>
|
||||
7
version4/.idea/encodings.xml
Normal file
7
version4/.idea/encodings.xml
Normal 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>
|
||||
20
version4/.idea/jarRepositories.xml
Normal file
20
version4/.idea/jarRepositories.xml
Normal 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
12
version4/.idea/misc.xml
Normal 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
6
version4/.idea/vcs.xml
Normal 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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
Binary file not shown.
Binary file not shown.
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -61,6 +61,7 @@ public class ConsumerTest {
|
||||
|
||||
// Gracefully shutdown the executor service
|
||||
executorService.shutdown();
|
||||
clientProxy.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
@ -109,4 +109,11 @@ public class ClientProxy implements InvocationHandler {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
//关闭创建的资源
|
||||
//注:如果在需要C-S保持长连接的场景下无需调用close方法
|
||||
public void close(){
|
||||
rpcClient.close();
|
||||
serviceCenter.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,4 +14,5 @@ import common.message.RpcResponse;
|
||||
|
||||
public interface RpcClient {
|
||||
RpcResponse sendRequest(RpcRequest request);
|
||||
void close();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -54,4 +54,9 @@ public class SimpleSocketRpcClient implements RpcClient {
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,4 +19,7 @@ public interface ServiceCenter {
|
||||
|
||||
//判断是否可重试
|
||||
boolean checkRetry(InetSocketAddress serviceAddress, String methodSignature);
|
||||
|
||||
//关闭客户端
|
||||
void close();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
});
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8
version6/.idea/.gitignore
vendored
Normal file
8
version6/.idea/.gitignore
vendored
Normal 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
|
||||
18
version6/.idea/compiler.xml
Normal file
18
version6/.idea/compiler.xml
Normal 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>
|
||||
17
version6/.idea/encodings.xml
Normal file
17
version6/.idea/encodings.xml
Normal 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>
|
||||
20
version6/.idea/jarRepositories.xml
Normal file
20
version6/.idea/jarRepositories.xml
Normal 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
14
version6/.idea/misc.xml
Normal 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
6
version6/.idea/vcs.xml
Normal 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
20
version6/krpc-api/pom.xml
Normal 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>
|
||||
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
26
version6/krpc-api/src/main/java/com/kama/pojo/User.java
Normal file
26
version6/krpc-api/src/main/java/com/kama/pojo/User.java
Normal 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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
BIN
version6/krpc-api/target/classes/com/kama/pojo/User.class
Normal file
BIN
version6/krpc-api/target/classes/com/kama/pojo/User.class
Normal file
Binary file not shown.
Binary file not shown.
32
version6/krpc-common/pom.xml
Normal file
32
version6/krpc-common/pom.xml
Normal 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>
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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]);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
111
version6/krpc-common/src/main/java/common/spi/SpiLoader.java
Normal file
111
version6/krpc-common/src/main/java/common/spi/SpiLoader.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
version6/krpc-common/target/classes/common/spi/SpiLoader.class
Normal file
BIN
version6/krpc-common/target/classes/common/spi/SpiLoader.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
version6/krpc-common/target/classes/common/util/ConfigUtil.class
Normal file
BIN
version6/krpc-common/target/classes/common/util/ConfigUtil.class
Normal file
Binary file not shown.
50
version6/krpc-consumer/pom.xml
Normal file
50
version6/krpc-consumer/pom.xml
Normal 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>
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
Binary file not shown.
Binary file not shown.
130
version6/krpc-core/pom.xml
Normal file
130
version6/krpc-core/pom.xml
Normal 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>
|
||||
@ -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
Loading…
Reference in New Issue
Block a user