Dubbo源码学习系列 手写简易RPC
Posted Dream_it_possible!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo源码学习系列 手写简易RPC相关的知识,希望对你有一定的参考价值。
前言
此文为了加深对RPC的理解,运用Socket网络编程技术手写一个精简版的RPC框架。
一、项目工程目录
二、手写服务端
服务端主要是接收请求----> 处理请求----> 响应结果。
package com.example.rpc.server;
import com.example.rpc.api.UserInterface;
import com.example.rpc.client.Invocation;
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.ServerSocket;
import java.net.Socket;
public class RpcServer {
public static void main(String[] args) {
while (true) {
try {
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("有新的连接过来了...");
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
try {
Invocation invocation = (Invocation) ois.readObject();
String interfaceName = invocation.getInterfaceName();
String methodName = invocation.getMethodName();
Class<?>[] paramsType = invocation.getParamsType();
Object[] params = invocation.getParams();
// 获取Class
Class clazz = null;
String tmp = UserInterface.class.getName();
if (interfaceName.equals(tmp)) {
clazz = UserInterfaceImpl.class;
} else {
throw new RuntimeException("无此接口!");
}
// 获取方法对象
Method method = clazz.getMethod(methodName, paramsType);
Object obj = method.invoke(clazz.newInstance(), params);
System.out.println("调用成功,结果为:" + obj);
// 回写结果
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(obj);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、客户端
客户端通过动态代理技术获取代理对象, 代理对象调用sayHello() 方法时,执行invoke()方法, 然后通过ois读取server返回的结果。
package com.example.rpc.client;
import com.example.rpc.api.UserInterface;
import com.example.rpc.model.User;
import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
public class RpcClient {
public static void main(String[] args) {
// 启动客户端
UserInterface userInterface = (UserInterface) RpcClient.getProxy(UserInterface.class);
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String result = userInterface.sayHello("binbing!");
System.out.println("调用成功,结果为:" + result);
}
}
private static Object getProxy(Class<UserInterface> userInterfaceClass) {
return Proxy.newProxyInstance(userInterfaceClass.getClassLoader(), new Class[]{userInterfaceClass}, (proxy, method, args) -> {
Socket socket = new Socket("localhost", 8080);
// 反射4要素: method , 接口实现类的class, 参数类型列表、参数列表。
// 1. 给服务端发送请求,向服务端写数据
Invocation invocation = new Invocation(userInterfaceClass.getName(), method.getName(), method.getParameterTypes(), args);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(invocation);
InputStream is = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
Object obj = ois.readObject();
return obj;
});
}
}
启动服务端后,再启动客户端:
以上是关于Dubbo源码学习系列 手写简易RPC的主要内容,如果未能解决你的问题,请参考以下文章
手写dubbo-7手撸了自定义协议远程调用服务动态扩容,梳理一下吧!