使用Socket实现一个简单的RPC
实现原理
consumer端使用jdk动态代理,代理要调用的接口建立socket连接,传入socket连接ip和端口号。
代理类发送socket连接,把封装的参数数据(需要类名、方法名、参数类型反射构建方法 执行咱们需要调用的方法)输出到socket中。
provider端接收接收(accept)socket消息,通过接收到的封装参数构建执行方法并写入socket返回。
具体实现
待调用接口类
public interface OrderApi {
String getOrderName(String name);
}
传输rpc参数
@Getter
@Setter
public class RpcRequest implements Serializable {
/**
* 方法名
*/
private String methodName;
/**
* 参数
*/
private Object[] args;
/**
* 参数的类型
*/
private Class[] types;
/**
* class的路径
*/
private String className;
}
consumer
启动应用发布端口消息
public class consumerApp {
public static void main(String[] args) {
ProxySocketClient proxySocketClient = new ProxySocketClient();
OrderApi orderApi = proxySocketClient.proxyClient(OrderApi.class, "127.0.0.1", 12356);
System.out.println(orderApi.getOrderName("发了一条消息!"));
}
}
生成JDK代理
public class ProxySocketClient {
/**
* 动态代理发送socket连接
*/
public <T> T proxyClient(final Class<T> clazz,String host,int port){
return (T) Proxy.newProxyInstance(clazz.getClassLoader(),new Class<?>[]{clazz},new RemInvocationHandler(host,port));
}
}
具体的代理类,发送socket
public class RemInvocationHandler implements InvocationHandler {
//socket连接主机
private String host;
//端口
private int port;
public RemInvocationHandler(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//封装rpc请求参数
RpcRequest rpcRequest = new RpcRequest();
rpcRequest.setArgs(args);
rpcRequest.setClassName(method.getDeclaringClass().getName());
rpcRequest.setTypes(method.getParameterTypes());
rpcRequest.setMethodName(method.getName());
RpcNetTransport rpcNetTransport = new RpcNetTransport(host,port);
//发送请求
System.out.println("发送请求");
return rpcNetTransport.send(rpcRequest);
}
}
把参数输入到socket中,并接收socket返回数据
public class RpcNetTransport{
//socket连接主机
private String host;
//端口
private int port;
public RpcNetTransport(String host, int port) {
this.host = host;
this.port = port;
}
public Socket newSocket() throws IOException {
return new Socket(host, port);
}
public Object send(RpcRequest rpcRequest) {
ObjectInputStream inputStream = null;
ObjectOutputStream outputStream = null;
try {
//建立socket连接
Socket socket = newSocket();
outputStream = new ObjectOutputStream(socket.getOutputStream());
//把封装的参数数据输出到socket中
outputStream.writeObject(rpcRequest);
outputStream.flush();
//接收socket返回数据
inputStream = new ObjectInputStream(socket.getInputStream());
return inputStream.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
provider
发布服务,待消费
public class ProducerApp {
public static void main( String[] args ) {
// new一个实例
OrderApi orderApi = new OrderController();
ProxySocketServer proxySocketServer = new ProxySocketServer();
// 发布服务
proxySocketServer.publisher(orderApi, 12356);
}
}
RPC调用接口的实现类
public class OrderController implements OrderApi {
@Override
public String getOrderName(String name) {
return "服务端响应:"+name;
}
}
接收socket
public class ProxySocketServer {
//开启多线程接收
private final ExecutorService executorService = Executors.newCachedThreadPool();
public void publisher(Object service,int port){
ServerSocket serverSocket = null;
try {
while (true){
//服务端接收socket建立连接
serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
//从socket获取数据
executorService.submit(new ProcessorHandler(service,socket));
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端具体接收执行方法实现
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() {
ObjectInputStream objectInputStream = null;
ObjectOutputStream objectOutputStream = null;
try {
//读取socket流转换
objectInputStream = new ObjectInputStream(socket.getInputStream());
//获取内容
RpcRequest rpcRequest = (RpcRequest) objectInputStream.readObject();
//执行调用方法
Object res = this.invoke(rpcRequest);
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(res);
objectOutputStream.flush();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}finally {
if(objectOutputStream!= null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(objectInputStream != null){
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Object invoke(RpcRequest rpcRequest) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//通过反射获取class
Class<?> clazz = Class.forName(rpcRequest.getClassName());
//获取方法(通过方法名+参数类型)
Method method = clazz.getMethod(rpcRequest.getMethodName(), rpcRequest.getTypes());
//传入参数(接口+方法参数)执行方法返回 ---provider端是具体接口的实现,调用接口返回
return method.invoke(service,rpcRequest.getArgs());
}
}