RPC 实现技术主要是通过数据的序列化跟反序列话实现的,通过序列化将数据编程二进制流,将数据传送到指定的位置后需要将数据进行反序列化,反序列化 后得到数据。所以这个DEMO主要实现技术是通过SOCKET-ServerSock + ObjectOutputStream实现PRC功能。这里主要有两个技术点,1是使用TCP连接保证连接的 稳定,另外一个是序列化的效率问题。目前流行的两个序列化工具是 Google的Protocal Buffers 效率高,代码侵入性较强,Hessian效率稍低,但是其对各 种编程语言有着良好的支持。且稳定性好。这里的Socket是阻塞式的,可以使用类似于Netty这种非阻塞式的框架用来实现RPC的调用。调用流程如下:1、 消费者通过获取SOcket连接,获取数据传输的线路,然后将数据序列化到服务提供者,服务提供者拿到数据后进行对应的服务调用,然后通过Socket进行数据 的返回。这样就能实现JAVA的RPC
public class Consumer {//消费者 public static void main(String[] args) throws Exception{ String interfaceName = UserService.class.getName(); //需要远程执行的方法 Method method = UserService.class.getMethod("getUserName", java.lang.String.class); //RPC参数 Object[] arguments = {"441622"}; //Socket数据通道 Socket socket = new Socket("172.29.224.87",1234); //序列化RPC调用参数 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); output.writeUTF(interfaceName); output.writeUTF(method.getName()); output.writeObject(method.getParameterTypes()); output.writeObject(arguments); //获取RPC返回结果 ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); Object result = input.readObject(); System.out.println((String)result); } }
public class Provider {//服务提供者 private static Map<String, Object> servicesPool = new HashMap<>(); public static void main(String[] args) throws Exception{ init(); System.out.println("RPC Server 启动"); @SuppressWarnings("resource") ServerSocket server = new ServerSocket(1234); while (true) { try { //开启SocketServer用于传输数据 Socket socket = server.accept(); //反序列化RPC调用数据包括,接口名称,方法名,参数类型,参数i ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); //接口名称 String interfacename = input.readUTF(); //方法名 String methodName = input.readUTF(); //参数类型 Class<?>[] paramterType = (Class<?>[])input.readObject(); //参数 Object[] params = (Object[]) input.readObject(); //将类加载到内存中 Class<?> serviceInterfaceclass = Class.forName(interfacename); //获取对象,线程安全的方法所以可以预先加载类,可以节省每次创建对内存处理器的消耗 Object service = servicesPool.get(interfacename); //根据方法名跟参数类型确认一个方法 Method method = serviceInterfaceclass.getMethod(methodName, paramterType); //调用方法 Object result = method.invoke(service, params); //根据socket通道返回RPC调用数据 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); output.writeObject(result); } catch (Exception e) { e.printStackTrace(); } } } public static void init(){ servicesPool.put("org.rpc.UserService", new UserServiceImpl()); } }
public interface UserService {//服务接口 /** * 获取身份证获取用户姓名 * @param helloArg 参数 * @return */ public String getUserName(String idCard); }
public class UserServiceImpl implements UserService{//服务实现 Map<String, String> userPool = new HashMap<String, String>(); public UserServiceImpl() { userPool.put("441621", "小张"); userPool.put("441622", "小王"); userPool.put("441623", "小刘"); } @Override public String getUserName(String idCard) { if(idCard == null){ return "参数异常"; } String userName = userPool.get(idCard); if(userName != null){ return userName; }else{ return "用户不存在"; } } }