手寫RPC框架V1
gitee地址:https://gitee.com/kylin1991_admin/rpc_handwriting
Api.jar
1、寫一個IHelloService接口,類似dubbo
public interface IHelloService {
String sayHello(String context);
}
2、一個RpcRequest請求模型
@Data
public class RpcRequest implements Serializable {
private String className;
private String methodName;
private Object[] parameters;
}
Server
1、Server 服務註冊
public class Server {
public static void main(String[] args) {
IHelloService helloService = new IHelloServiceImpl();
RpcProxyServer rpcProxyServer = new RpcProxyServer(helloService,8080);
rpcProxyServer.publisher();
}
}
2、RpcProxyServer 服務發佈
public class RpcProxyServer {
private Object service;
private int port;
public RpcProxyServer(Object service, int port) {
this.service = service;
this.port = port;
}
public void publisher() {
try {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
Socket socket = serverSocket.accept();
executor.execute(new ProcessorHandler(service,socket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static final Executor executor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(),
Runtime.getRuntime().availableProcessors(),
60L,
TimeUnit.MINUTES,
new ArrayBlockingQueue<>(Runtime.getRuntime().availableProcessors()),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
}
3、請求處理ProcessorHandler
public class ProcessorHandler implements Runnable {
private Object service;
private Socket socket;
public ProcessorHandler(Object service, Socket socket) {
this.service = service;
this.socket = socket;
}
@Override
public void run() {
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream())) {
// 接受請求
RpcRequest rpcRequest = (RpcRequest) objectInputStream.readObject();
// 反射調用並且返回結果
objectOutputStream.writeObject(invoke(rpcRequest));
objectOutputStream.flush();
} catch (IOException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Object invoke(RpcRequest rpcRequest, Object service) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clazz = Class.forName(rpcRequest.getClassName());
Class<?>[] parametersTypes = new Class<?>[rpcRequest.getParameters().length];
for (int i = 0; i < parametersTypes.length; i++) {
parametersTypes[i] = rpcRequest.getParameters()[i].getClass();
}
Method method = clazz.getMethod(rpcRequest.getMethodName(), parametersTypes);
return method.invoke(service, rpcRequest.getParameters());
}
}
Client
1、Client 發起請求
public class Client {
public static void main(String[] args) {
RpcProxyClient rpcProxyClient = new RpcProxyClient();
IHelloService helloService = rpcProxyClient.proxyClient(IHelloService.class,"localhost",8080);
System.out.println(helloService.sayHello("lilei"));;
}
}
2、遠程調用(採用jdk動態代理)
- RpcProxyClient
public class RpcProxyClient {
public <T> T proxyClient(Class<?> interfacesCls, String host, int port) {
return (T) Proxy.newProxyInstance(
interfacesCls.getClassLoader(),
new Class<?>[]{interfacesCls},
new RemoteInvocationHandler(host,port));
}
}
- RemoteInvocationHandler 用於遠程方法調用
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 rpcRequest = new RpcRequest();
rpcRequest.setClassName(method.getDeclaringClass().getName());
rpcRequest.setMethodName(method.getName());
rpcRequest.setParameters(args);
//發送請求,並且獲得結果
RpcNetTransport rpcNetTransport = new RpcNetTransport(host, port);
return rpcNetTransport.send(rpcRequest);
}
}
3、RpcNetTransport 調用
public class RpcNetTransport {
private String host;
private int port;
public RpcNetTransport(String host, int port) {
this.host = host;
this.port = port;
}
public Object send(RpcRequest rpcRequest) {
Object result = null;
try (Socket socket = new Socket(host, port);
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream())) {
objectOutputStream.writeObject(rpcRequest);
objectOutputStream.flush();
result = objectInputStream.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return result;
}
}
測試
1、啓動Server
2、啓動Client
測試成功!