手写RPC框架
一、前言
二、简介
三、手写RPC框架
在rpc远程调用服务中,存在生产者和消费者,建立生产者rpcserver工程,消费者rpcclient工程;
生产者工程目录结构:
接口作为将要发布的服务
package com.server.rpc;
//将要发布的服务接口
public interface SayHello {
public String sayHello(String args);
}
服务调用间传输类
package com.server.rpc;
import java.io.Serializable;
import java.util.Arrays;
public class RpcRequestBean implements Serializable {
private String className;
private String methodName;
private Object[] params;
@Override
public String toString() {
return "RpcRequestBean{" +
"className='" + className + '\'' +
", methodName='" + methodName + '\'' +
", params=" + Arrays.toString(params) +
'}';
}
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[] getParams() {
return params;
}
public void setParams(Object[] params) {
this.params = params;
}
}
生产者工程中rpc-server-provide模块需引入rpc-server-api工程jar包实现接口
<dependency>
<groupId>com.soft.rpc</groupId>
<artifactId>rpc-server-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
服务实现类
```java
package com.server.rpc;
public class SayHelloImpl implements SayHello {
public String sayHello(String args) {
return "hello: First Rpc demo";
}
}
创建服务发布类
package com.server.rpc;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RpcProxyServer {
private ExecutorService executorService= Executors.newCachedThreadPool();
/**
*
* @param service 要发布的服务
* @param port 暴露的端口号
*/
public void publisher(Object service, int port) throws IOException {
ServerSocket serverSocket=null;
try {
serverSocket = new ServerSocket(port);
while (true) {
final Socket socket = serverSocket.accept();
// socket.getInputStream(); 阻塞IO
//进入下一步骤,说明有客户端连接进来
executorService.execute(new ProcessHandle(socket,service));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (serverSocket != null) {
serverSocket.close();
}
}
}
}
```创建线程执行客户端请求
```java
package com.server.rpc;
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;
public class ProcessHandle implements Runnable {
private Socket socket;
private Object service;
public ProcessHandle(Socket socket, Object service) {
this.socket = socket;
this.service = service;
}
public void run() {
ObjectInputStream objectInputStream = null;
ObjectOutputStream objectOutputStream = null;
try {
objectInputStream = new ObjectInputStream(socket.getInputStream());
//请求的方法,参数,名称,目标类,反序列化
RpcRequestBean rpcRequestBean = (RpcRequestBean) objectInputStream.readObject();
Object result = invoke(rpcRequestBean);
objectOutputStream=new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(result);//序列化,写入到通信管道
objectOutputStream.flush();
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}finally {
if (objectInputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (objectOutputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Object invoke(RpcRequestBean rpcRequestBean) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object[] args = rpcRequestBean.getParams();//请求参数
Class<?>[] types =null;
if (args.length > 0) {
types = new Class[args.length];
for (int i = 0; i < args.length; i++) {
types[i]=args[i].getClass();
}
}
//反射加载对应的类
Class<?> clazz = Class.forName(rpcRequestBean.getClassName());
//通过反射找到对应class中的方法
Method method = clazz.getMethod(rpcRequestBean.getMethodName(), types);
Object result = method.invoke(service, args);
return result;
}
}
```创建服务启动类,发布服务
```java
package com.server.rpc;
import java.io.IOException;
public class SendServer {
public static void main(String[] args) throws IOException {
SayHelloImpl sayHello = new SayHelloImpl();
RpcProxyServer rpcProxyServer = new RpcProxyServer();
rpcProxyServer.publisher(sayHello,8888);
}
}
消费者工程目录结构:*
消费者工程引入生产者工程依赖
<dependency>
<groupId>com.soft.rpc</groupId>
<artifactId>rpc-server-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
请求服务启动类
package com.rpc;
import com.server.rpc.SayHello;
public class GetService {
public static void main(String[] args) {
RpcProxyClient rpcProxyClient = new RpcProxyClient();
SayHello sayHello=rpcProxyClient.clientProxy(SayHello.class, "localhost", 8888);
System.out.println(sayHello.sayHello("s"));
}
}
动态代理请求
package com.rpc;
import java.lang.reflect.Proxy;
public class RpcProxyClient {
public <T> T clientProxy(final Class<T> interFaceClas, final String host
,final int port) {//interface com.server.rpc.SayHello
return (T) Proxy.newProxyInstance(interFaceClas.getClassLoader(),
new Class<?>[]{interFaceClas}, new RemoteInvocationHandle(host,port));
}
}
代理类请求服务结果处理
package com.rpc;
import com.server.rpc.RpcRequestBean;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class RemoteInvocationHandle implements InvocationHandler {
private String host;
private int port;
public RemoteInvocationHandle(String host, int port) {
this.host = host;
this.port = port;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("begin" + host + "->" + port);
RpcRequestBean rpcRequestBean = new RpcRequestBean();
rpcRequestBean.setClassName(method.getDeclaringClass().getName());//com.server.rpc.SayHello
rpcRequestBean.setMethodName(method.getName());//sayHello
rpcRequestBean.setParams(args);
RpcNetTransport rpcNetTransport = new RpcNetTransport(host, port);
Object result = rpcNetTransport.send(rpcRequestBean);
return result;
}
}
构建服务调用类
package com.rpc;
import com.server.rpc.RpcRequestBean;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class RpcNetTransport {
private String host;
private int port;
public RpcNetTransport(String host, int port) {
this.host = host;
this.port = port;
}
public Object send(RpcRequestBean rpcRequestBean) {//RpcRequestBean{className='com.server.rpc.SayHello', methodName='sayHello', params=[s]}
//构建服务端请求,把request写入到服务端
Socket socket=null;
ObjectOutputStream objectOutputStream = null;
ObjectInputStream objectInputStream = null;
Object result =null;
try {
socket = new Socket(host, port);
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(rpcRequestBean);
objectOutputStream.flush();
//得到服务端返回结果
objectInputStream = new ObjectInputStream(socket.getInputStream());
result = objectInputStream.readObject();//hello: First Rpc demo
} catch (Exception e) {
e.printStackTrace();
}finally {
if (objectInputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (objectOutputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
分别启动生产者工程和消费者工程,消费者端运行结果显示: