RPC-基于原生java实现
Posted cui-s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RPC-基于原生java实现相关的知识,希望对你有一定的参考价值。
一:什么是RPC
远程过程调用(Remote Procedure Call)。就是调用其他业务方的方法的时候,就像是调用自己本地的方法一样。
二:java rpc实现简介
服务端(使用反射)
(1)服务端写一个接口和一个接口的实现。
(2)服务端维护一个map,key为接口的类名,value为接口的实现类。
(3)服务端通过 ServerSocket 接收客户端发送过来的数据(接口的类名,方法名,请求参数)
(4)服务端根据接口的类名和方法名得到对应实现类的方法,通过反射调用服务
(5)把处理之后的结果通过 ServerSocket 返回给客户端
客户端(动态代理)
(1)把服务端的接口copy过来
(2)写一个代理类,调用服务端方法的时候,通过代理类的 invoke 方法把服务需要的 接口类名,方法名,请求参数 通过 Socket 发送给服务端;接收服务端处理的结果
三:具体实现的代码
(1)服务端的接口声明
public interface IHello String sayHello(String string);
(2)服务端接口的实现(真正干活的类)
public class HelloServiceImpl implements IHello @Override public String sayHello(String string) // TODO Auto-generated method stub return "你好:" + string;
(3)服务端的服务类
import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; public class RpcServer private static final HashMap<String, Class<?>> serviceRegistry = new HashMap<>(); private int port; public RpcServer(int port) this.port =port; public RpcServer register(Class serviceInterface, Class impl) serviceRegistry.put(serviceInterface.getName(), impl); return this; public void run() throws IOException ServerSocket server = new ServerSocket(); server.bind(new InetSocketAddress (port)); System.out.println("start server"); ObjectInputStream input =null; ObjectOutputStream output =null; Socket socket=null; try while(true) socket = server.accept (); input =new ObjectInputStream(socket.getInputStream()); String serviceName = input.readUTF(); String methodName = input.readUTF(); System.out.println ("客户端调用了 " + methodName + "方法"); Class<?>[] parameterTypes = (Class<?>[]) input.readObject(); Object[] arguments = (Object[]) input.readObject(); Class serviceClass = serviceRegistry.get(serviceName); if (serviceClass == null) throw new ClassNotFoundException(serviceName + " not found"); Method method = serviceClass.getMethod(methodName, parameterTypes); Object result = method.invoke(serviceClass.newInstance(), arguments); output = new ObjectOutputStream (socket.getOutputStream()); output.writeObject(result); catch (Exception e) e.printStackTrace(); public static void main(String[] args) throws IOException new RpcServer (8888).register(IHello.class,HelloServiceImpl.class).run();
(4)客户端的实现
import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.InetSocketAddress; import java.net.Socket; import com.cs.rpc.nativ.server.IHello; public class RpcClientProxy<T> implements InvocationHandler private Class<T> serviceInterface;//被调用者的接口声明 private InetSocketAddress addr;//被调用者的地址(ip+port) public RpcClientProxy(Class<T> serviceInterface, String ip,String port) this.serviceInterface = serviceInterface; this.addr = new InetSocketAddress(ip, Integer.parseInt ( port )); public T getClientIntance() return (T) Proxy.newProxyInstance (serviceInterface.getClassLoader(),new Class<?>[]serviceInterface,this); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable Socket socket = null; ObjectOutputStream output = null; ObjectInputStream input = null; try // 2.创建Socket客户端,根据指定地址连接远程服务提供者 socket = new Socket(); socket.connect(addr); // 3.将远程服务调用所需的接口类、方法名、参数列表等编码后发送给服务提供者 output = new ObjectOutputStream(socket.getOutputStream()); output.writeUTF(serviceInterface.getName()); output.writeUTF(method.getName()); output.writeObject(method.getParameterTypes()); output.writeObject(args); // 4.同步阻塞等待服务器返回应答,获取应答后返回 input = new ObjectInputStream(socket.getInputStream()); return input.readObject(); finally if (socket != null) socket.close(); if (output != null) output.close(); if (input != null) input.close(); public static void main(String[] args) RpcClientProxy client = new RpcClientProxy<>(IHello.class,"localhost","8888"); IHello hello = (IHello) client.getClientIntance (); System.out.println (hello.sayHello ( "socket rpc" ));
以上是关于RPC-基于原生java实现的主要内容,如果未能解决你的问题,请参考以下文章
java 从零开始手写 RPC (05) reflect 反射实现通用调用之服务端