first commit
This commit is contained in:
commit
3661cfa8e7
|
|
@ -0,0 +1,35 @@
|
|||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
info.text
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# 手写RPC框架
|
||||
|
||||
> RPC:让你像是在做本地调用一样去调用一个远程服务器上的方法
|
||||
|
||||
## RPC相关图示
|
||||
|
||||
RPC简单示意图
|
||||

|
||||
|
||||
RPC时序图
|
||||

|
||||
|
||||
手写RPC简易流程图
|
||||

|
||||
|
||||
## RPC需要解决的内容
|
||||
|
||||
- 必须要有服务暴露
|
||||
- 必须要有远程代理对象
|
||||
- 通信
|
||||
- 序列化与反序列化
|
||||
- IO
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
|
|
@ -0,0 +1,35 @@
|
|||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.shockkid</groupId>
|
||||
<artifactId>rpc</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.0</version>
|
||||
<modules>
|
||||
<module>rpc-api</module>
|
||||
<module>rpc-server</module>
|
||||
<module>rpc-client</module>
|
||||
</modules>
|
||||
|
||||
<name>rpc</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.shockkid</groupId>
|
||||
<artifactId>rpc-api</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<name>rpc-api</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.shockkid;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*
|
||||
*/
|
||||
public class App
|
||||
{
|
||||
public static void main( String[] args )
|
||||
{
|
||||
System.out.println( "Hello World!" );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.shockkid;
|
||||
|
||||
/**
|
||||
* @auther lisang
|
||||
* @date 2024/6/27 17:02
|
||||
**/
|
||||
public interface HelloServer {
|
||||
public String sayHello(String content);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package com.shockkid;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @auther lisang
|
||||
* @date 2024/6/27 16:59
|
||||
**/
|
||||
public class RpcRequest implements Serializable {
|
||||
private String className;
|
||||
private String methodName;
|
||||
private Object[] parameters;
|
||||
private Class[] types;
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public void setClassName(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
public void setMethodName(String methodName) {
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
public Object[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(Object[] parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public Class[] getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
||||
public void setTypes(Class[] types) {
|
||||
this.types = types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RpcRequest{" +
|
||||
"className='" + className + '\'' +
|
||||
", methodName='" + methodName + '\'' +
|
||||
", parameters=" + Arrays.toString(parameters) +
|
||||
", types=" + Arrays.toString(types) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.shockkid;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class AppTest
|
||||
{
|
||||
/**
|
||||
* Rigorous Test :-)
|
||||
*/
|
||||
@Test
|
||||
public void shouldAnswerWithTrue()
|
||||
{
|
||||
assertTrue( true );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.shockkid</groupId>
|
||||
<artifactId>rpc-client</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<name>rpc-client</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.shockkid</groupId>
|
||||
<artifactId>rpc-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.shockkid;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*/
|
||||
public class Client {
|
||||
public static void main(String[] args) {
|
||||
RpcProxyClient rpcProxyClient = new RpcProxyClient();
|
||||
HelloServer helloServer = rpcProxyClient.clientProxy(HelloServer.class, "localhost", 8081);
|
||||
Object obj = helloServer.sayHello("lisang");
|
||||
System.out.println(obj.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.shockkid;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @auther lisang
|
||||
* @date 2024/6/27 19:51
|
||||
**/
|
||||
public class RemoteInvocationHandler implements InvocationHandler {
|
||||
private String host;
|
||||
private int port;
|
||||
|
||||
public RemoteInvocationHandler(String host, int port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
RpcRequest request = new RpcRequest();
|
||||
request.setClassName(method.getDeclaringClass().getName());
|
||||
request.setMethodName(method.getName());
|
||||
request.setParameters(args);
|
||||
request.setTypes(method.getParameterTypes());
|
||||
RpcNetTransport rpcNetTransport = new RpcNetTransport(host, port);
|
||||
return rpcNetTransport.send(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package com.shockkid;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* @auther lisang
|
||||
* @date 2024/6/27 19:56
|
||||
**/
|
||||
public class RpcNetTransport {
|
||||
private String host;
|
||||
private int port;
|
||||
|
||||
public RpcNetTransport(String host, int port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
private Socket newSocket() throws IOException {
|
||||
System.out.println("开始建立一个连接");
|
||||
Socket socket = null;
|
||||
socket = new Socket(host, port);
|
||||
return socket;
|
||||
}
|
||||
|
||||
public Object send(RpcRequest request) {
|
||||
Socket socket = null;
|
||||
Object result = null;
|
||||
ObjectOutputStream os = null;
|
||||
ObjectInputStream is = null;
|
||||
try {
|
||||
socket = newSocket();
|
||||
os = new ObjectOutputStream(socket.getOutputStream());
|
||||
os.writeObject(request);
|
||||
is = new ObjectInputStream(socket.getInputStream());
|
||||
result = is.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (os != null) {
|
||||
try {
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.shockkid;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
/**
|
||||
* @auther lisang
|
||||
* @date 2024/6/27 20:07
|
||||
**/
|
||||
public class RpcProxyClient {
|
||||
public <T> T clientProxy(Class interfacecls, String host, int port) {
|
||||
return (T) Proxy.newProxyInstance(interfacecls.getClassLoader(),
|
||||
new Class[]{interfacecls},
|
||||
new RemoteInvocationHandler(host, port));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.shockkid;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class AppTest
|
||||
{
|
||||
/**
|
||||
* Rigorous Test :-)
|
||||
*/
|
||||
@Test
|
||||
public void shouldAnswerWithTrue()
|
||||
{
|
||||
assertTrue( true );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.shockkid</groupId>
|
||||
<artifactId>rpc-server</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<name>rpc-server</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.shockkid</groupId>
|
||||
<artifactId>rpc-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.shockkid;
|
||||
|
||||
/**
|
||||
* @auther lisang
|
||||
* @date 2024/6/27 17:03
|
||||
**/
|
||||
public class HelloServerImpl implements HelloServer {
|
||||
@Override
|
||||
public String sayHello(String content) {
|
||||
return "shockkid " + content + " say hello";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.shockkid;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* @auther lisang
|
||||
* @date 2024/6/27 17:12
|
||||
**/
|
||||
public class ProcessorHandler implements Runnable {
|
||||
Socket socket = null;
|
||||
Object service = null;
|
||||
|
||||
public ProcessorHandler(Socket socket, Object service) {
|
||||
this.socket = socket;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ObjectInputStream is = null;
|
||||
ObjectOutputStream os = null;
|
||||
|
||||
try {
|
||||
is = new ObjectInputStream(socket.getInputStream());
|
||||
RpcRequest rpcRequest = (RpcRequest) is.readObject();
|
||||
Object result = invoke(rpcRequest);
|
||||
|
||||
os = new ObjectOutputStream(socket.getOutputStream());
|
||||
os.writeObject(result);
|
||||
os.flush();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private Object invoke(RpcRequest request) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
Class clazz = Class.forName(request.getClassName());
|
||||
Object[] args = request.getParameters();
|
||||
Method method = clazz.getMethod(request.getMethodName(), request.getTypes());
|
||||
Object obj = method.invoke(service, args);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.shockkid;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* @auther lisang
|
||||
* @date 2024/6/27 17:06
|
||||
**/
|
||||
public class RpcProxyServer {
|
||||
private ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
|
||||
public void publisher(Object server,int prot) {
|
||||
ServerSocket serverSocket = null;
|
||||
try {
|
||||
serverSocket = new ServerSocket(prot);
|
||||
while (true) {
|
||||
Socket socket = serverSocket.accept();
|
||||
executorService.execute(new ProcessorHandler(socket, server));
|
||||
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.shockkid;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*/
|
||||
public class Server {
|
||||
public static void main(String[] args) {
|
||||
HelloServer helloServer = new HelloServerImpl();
|
||||
RpcProxyServer rpcProxyServer = new RpcProxyServer();
|
||||
rpcProxyServer.publisher(helloServer, 8081);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.shockkid;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class AppTest
|
||||
{
|
||||
/**
|
||||
* Rigorous Test :-)
|
||||
*/
|
||||
@Test
|
||||
public void shouldAnswerWithTrue()
|
||||
{
|
||||
assertTrue( true );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.shockkid;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*
|
||||
*/
|
||||
public class App
|
||||
{
|
||||
public static void main( String[] args )
|
||||
{
|
||||
System.out.println( "Hello World!" );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.shockkid;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class AppTest
|
||||
{
|
||||
/**
|
||||
* Rigorous Test :-)
|
||||
*/
|
||||
@Test
|
||||
public void shouldAnswerWithTrue()
|
||||
{
|
||||
assertTrue( true );
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue