-
Concept to explain
Remote Procedure Call Protocol (RPC) is a Protocol that requests services from Remote computer programs over the network without understanding the underlying network technology. RPC uses client/server mode. The requester is a client and the service provider is a server. First, the client calling process sends an invocation message with process parameters to the server process and then waits for the reply message. On the server side, the process stays asleep until the call message arrives. When a call message arrives, the server gets the process parameters, calculates the result, sends the reply message, and waits for the next call message. Finally, the client calling process receives the reply message, gets the process result, and the call execution continues.
-
ServerSocket and Socket
- Basic principles of establishing a connection between a client and a server
- Procedure For establishing a connection between a client and a server
-
ServerSocket
ServerSocket server = new ServerSocket(1234); Socket socket = server.accept(); Copy the code
Create and listen on a ServerSocket object with port 1234, and call the Accept () method of the ServerSocket object. This method will block the application on the Server side until it catches a request from the Client side. And returns a Socket object used to communicate with the Client. After that, as long as the Server program reads and writes data to the Socket object, it can realize reading and writing data to the remote Client. When you end listening, close the ServerSocket object
-
Socket
Socket socket = new Socket("127.0.0.1".1234);Copy the code
The client creates a socket object and establishes a connection with the server. The server manages the client connection requests by the operating system. The operating system stores the connection requests in a first-in, first-out queue, which is usually 50 in length. When the server connection queue length is greater than 50, the connection is rejected.
- Basic principles of establishing a connection between a client and a server
-
Dynamic Proxy In Java, there are two important classes and interfaces, Proxy and InvocationHandler, which are included in the java.lang.Reflect package. These classes and interfaces are required to implement dynamic Proxy
-
Proxy Proxy is used to create a Proxy class object. It provides many methods, of which the newProxyInstance method is the most used.
public static Object newProxyInstance(ClassLoader loader, Class<? >[] interfaces, InvocationHandler h)Copy the code
Loader: a ClassLoader object that defines which ClassLoader interfaces the proxy object is loaded by: An array of interfaces that represents the set of interfaces we will provide to the proxy object. If I provide a set of interfaces, the proxy object claims to implement the set of interfaces, so we can call the corresponding interface through the proxy object h: An InvocationHandler object that represents the object that the dynamic proxy object executes when the method is called
-
Each dynamic proxy class must implement the InvocationHandler interface, and each instance of the proxy class is associated with an InvocationHandler object. When the proxy object calls a method, The invocation of this method is mapped to the Invoke method execution of InvocationHandler
public Object invoke(Object proxy, Method method.Object[] args)Copy the code
Parameter description: Proxy: indicates the real object of the proxy. Method: indicates a method of the real object to be invoked. Args: indicates the parameters accepted when the method of the real object is invoked
-
Dynamic proxy example
-
Defining the test interface
public interface TestHello { void hello(String name); void sayGood(); }Copy the code
-
Define interface implementation
public class TestHelloImpl implements TestHello{ @Override public void hello(String name) { System.out.println("hello " + name); } @Override public void sayGood() { System.out.println("you are the best!"); }}Copy the code
-
Define dynamic proxy classes
public class MyProxy implements InvocationHandler { private Object proxy; public MyProxy(Object proxy) { this.proxy = proxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { method.invoke(this.proxy, args); return null; }}Copy the code
-
Mock proxy invocation
public class Client { public static void main(String[] args) { TestHello th = new TestHelloImpl(); MyProxy mp = new MyProxy(th); TestHello thProxy = (TestHello) Proxy.newProxyInstance(mp.getClass().getClassLoader(), th.getClass().getInterfaces(), mp); thProxy.hello("Jerry"); thProxy.sayGood(); }}Copy the code
-
Test output
hello Jerry you are the best!Copy the code
-
-
-
A simple RPC implementation
-
Simple RPC framework class, define service registration method export, service consumption method refer
public class RpcFramework { /** ** Exposure services ** @paramService Service implementation * @paramPort Service port * @throws Exception */ public static void export(final Object service, int port) throws Exception { if (service == null) throw new IllegalArgumentException("service instance == null"); if (port <= 0 || port > 65535) throw new IllegalArgumentException("Invalid port " + port); System.out.println("Export service " + service.getClass().getName() + " on port " + port); ServerSocket server = new ServerSocket(port); for(;;) { try { final Socket socket = server.accept(); new Thread(new Runnable() { @Override public void run() { try { try { ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); try{ String methodName = input.readUTF(); Class<? >[] parameterTypes = (Class<? >[])input.readObject(); Object[] arguments = (Object[])input.readObject(); ObjectOutputStream output =new ObjectOutputStream(socket.getOutputStream()); try { Method method = service.getClass().getMethod(methodName, parameterTypes); Object result = method.invoke(service, arguments); output.writeObject(result); } catch (Throwable t) { output.writeObject(t); } finally{ output.close(); }}finally{ input.close(); }}finally{ socket.close(); }}catch (Exception e) { e.printStackTrace(); } } }).start(); } catch(Exception e) { e.printStackTrace(); }}}/** ** references service ** @param<T> Interface generic * @paramInterfaceClass Interface type * @paramHost Indicates the host name of the server @paramPort Indicates the server port * @returnRemote Service @throws Exception */ @SuppressWarnings("unchecked") public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception { if (interfaceClass == null) throw new IllegalArgumentException("Interface class == null"); if (! interfaceClass.isInterface()) throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!"); if (host == null || host.length() == 0) throw new IllegalArgumentException("Host == null!"); if (port <= 0 || port > 65535) throw new IllegalArgumentException("Invalid port " + port); System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port); return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), newClass<? >[] {interfaceClass},new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable { Socket socket = new Socket(host, port); try { ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); try { output.writeUTF(method.getName()); output.writeObject(method.getParameterTypes()); output.writeObject(arguments); InputStream is = socket.getInputStream(); ObjectInputStream input = new ObjectInputStream(is); try { Object result = input.readObject(); if (result instanceof Throwable) { throw (Throwable) result; } return result; } finally{ input.close(); }}finally{ output.close(); }}finally{ socket.close(); }}}); }}Copy the code
-
Define concrete interfaces and implementations
public interface HelloService { String hello(String name); }Copy the code
public class HelloServiceImpl implements HelloService{ @Override public String hello(String name) { return "hello "+ name; }}Copy the code
-
Generate and register service objects to the server
public class RpcProvider { public static void main(String[] args) { try { HelloService service = new HelloServiceImpl(); RpcFramework.export(service, 1235); } catch(Exception e) { e.printStackTrace(); }}}Copy the code
-
The client declares the service object defined by the server and consumes the service
public class RpcConsumer { public static void main(String[] args) { try { HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1".1235); for (int i = 0; i < Integer.MAX_VALUE; i ++) { String hello = service.hello("World" + i); System.out.println(hello); Thread.sleep(1000); }}catch(Exception e) { e.printStackTrace(); }}}Copy the code
-
-
note
- Most of the content of this article is not original, only for learning to use, welcome correction!
-
reference
- A few lines of RPC framework code should suffice
- ServerSocket usage details
- Simple implementation of connection-oriented Socket Server
- Java dynamic proxy mechanism details