RPC of TCP Introduction
In this paper, a simple rpc call framework is implemented by using socket programming of java. It is composed of two projects named batchake provider (service provider) and batchake consumer (service caller).
The design idea is as follows: 1. In the battery cake provider, write a service called battery cake service
2. In the batchake provider, start RpcProvider and publish the service
3. In the battery cake consumer, start the test class RpcTest
4. In battery cake consumer, the dynamic proxy class of BatterCakeService$Proxy0 is obtained by using jdk dynamic proxy
5. In battercake consumer, the dynamic proxy class BatterCakeService$Proxy0 establishes a socket connection with the battercake provider. For each connection, the battercake provider will start a ServerThread to process the request, and the proxy class will send related information such as service parameters
6. Receive the result returned by the server thread request of the batslake provider in the batslake consumer.
The above process sequence diagram is as follows
image
Next on the code!! Service provider
The project of this part is battery cake provider, and the project structure is shown in the figure below
Code of the part used first First, create a microservice. The interface is as follows
package com.rjzheng.service; public interface BatterCakeService { /** * Pancake service * @param name * @return */ public String sellBatterCake(String name); }
package com.rjzheng.service.impl; import com.rjzheng.service.BatterCakeService; public class BatterCakeServiceImpl implements BatterCakeService { @Override public String sellBatterCake(String name) { // TODO Auto-generated method stub return name+"A pancake,Very good sales"; } }
package com.rjzheng.start; import com.rjzheng.rpc.RpcProvider; import com.rjzheng.service.BatterCakeService; import com.rjzheng.service.impl.BatterCakeServiceImpl; public class RpcBootStrap { public static void main(String[] args) throws Exception { BatterCakeService batterCakeService =new BatterCakeServiceImpl(); //Release pancake selling service, registered at port 20006 RpcProvider.export(20006,batterCakeService); } }
package com.rjzheng.rpc; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * RPC Service provider * @author zhengrongjun * */ public class RpcProvider { //Store the list of registered services private static List<Object> serviceList; /** * Publish rpc service * @param object * @param port * @throws Exception */ public static void export(int port,Object... services) throws Exception { serviceList=Arrays.asList(services); ServerSocket server = new ServerSocket(port); Socket client = null; while (true) { //Block wait input client = server.accept(); //For each request, start a thread to process new Thread(new ServerThread(client,serviceList)).start(); } } }
package com.rjzheng.rpc; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Method; import java.net.Socket; import java.util.List; public class ServerThread implements Runnable { private Socket client = null; private List<Object> serviceList = null; public ServerThread(Socket client, List<Object> service) { this.client = client; this.serviceList = service; } @Override public void run() { ObjectInputStream input = null; ObjectOutputStream output = null; try { input = new ObjectInputStream(client.getInputStream()); output = new ObjectOutputStream(client.getOutputStream()); // Read the service the client wants to access Class serviceClass = (Class) input.readObject(); // Find the service class Object obj = findService(serviceClass); if (obj == null) { output.writeObject(serviceClass.getName() + "Service not found"); } else { //Call this method with reflection, return the result try { String methodName = input.readUTF(); Class<?>[] parameterTypes = (Class<?>[]) input.readObject(); Object[] arguments = (Object[]) input.readObject(); Method method = obj.getClass().getMethod(methodName, parameterTypes); Object result = method.invoke(obj, arguments); output.writeObject(result); } catch (Throwable t) { output.writeObject(t); } } } catch (Exception e) { e.printStackTrace(); } finally { try { client.close(); input.close(); output.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private Object findService(Class serviceClass) { // TODO Auto-generated method stub for (Object obj : serviceList) { boolean isFather = serviceClass.isAssignableFrom(obj.getClass()); if (isFather) { return obj; } } return null; } }
package com.rjzheng.rpc; import java.lang.reflect.Proxy; public class RpcConsumer { public static <T> T getService(Class<T> clazz,String ip,int port) { ProxyHandler proxyHandler =new ProxyHandler(ip,port); return (T)Proxy.newProxyInstance(RpcConsumer.class.getClassLoader(), new Class<?>[] {clazz}, proxyHandler); } }
package com.rjzheng.rpc; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.net.Socket; import com.rjzheng.service.BatterCakeService; public class ProxyHandler implements InvocationHandler { private String ip; private int port; public ProxyHandler(String ip, int port) { // TODO Auto-generated constructor stub this.ip = ip; this.port = port; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Socket socket = new Socket(this.ip, this.port); ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); try { output.writeObject(proxy.getClass().getInterfaces()[0]); output.writeUTF(method.getName()); output.writeObject(method.getParameterTypes()); output.writeObject(args); output.flush(); Object result = input.readObject(); if(result instanceof Throwable) { throw (Throwable) result; } return result; } finally { socket.shutdownOutput(); } } }
package com.rjzheng.start; import com.rjzheng.rpc.RpcConsumer; import com.rjzheng.service.BatterCakeService; public class RpcTest { public static void main(String[] args) { BatterCakeService batterCakeService=RpcConsumer.getService(BatterCakeService.class, "127.0.0.1", 20006); String result=batterCakeService.sellBatterCake("Double egg"); System.out.println(result); } }