Remote Procedure Call (RPC). A node requests services provided by another node

To understand remote calls, it is essential to understand local calls first

A local call

In our original singleton application project all the requests were local calls. For example: to modify a student’s information, the foreground HTTP requests the back-end interface first, calls the function specification provided by the current project for parameter transmission, and finally realizes the call modification function

The remote invocation

In the process of appeal, the local HTTP requests the current project to improve student modify functions, but the real change function service running in another project, that is to say you true to access services in another host, you are in the current request interface function change is actually involved RPC process of a call to the local request call transfer, The local service then sends a data request to another host and receives the data return from the server. The current request is equivalent to the Client.



In the design of microservices, if A service A accesses service B under another Module, it can use HTTP REST to transfer data and carry out serialization and deserialization operations between the two services, and service B returns the execution results.

Why not just Http

When you look at the remote call process above, you might wonder, why doesn’t the client directly remote the HTTP request server? There are two main reasons: 1.HTTP is completed in the application layer, and the cost of the whole communication is high. Remote procedure calls are directly made based on TCP, and data transmission is completed in the TCP layer of the transport layer, which is more suitable for scenarios requiring high efficiency. The underlying implementation is more complex than REST. 2. Because of the adoption of RPC, various vendors follow the RPC specification to adapt to different platforms, and the specific call transmission, which serialization technology is chosen by them, so there are many RPC frameworks, such as Dubbo

The following will be attached with the process of custom RPC implementation source code, it is recommended that you do not understand the Socket IO network to understand these basic concepts

The Server side

Business logic code

package com.demo.provider;

import rpcservice.RpcRequest;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;

public class ProcessorHandler implements Runnable{

    private Socket socket;
    private Object service;

    public ProcessorHandler(Socket socket, Object service) {
        this.socket = socket;
        this.service = service;
    }

    @Override
    public void run(a)  {
        ObjectOutputStream objectOutputStream = null;
        ObjectInputStream objectInputStream = null;
        try {
            // Obtain the input flow of the client request and related parameter information
            objectInputStream = new ObjectInputStream(socket.getInputStream());
            // Convert the flow information to objects
            RpcRequest request = (RpcRequest)objectInputStream.readObject();
            // Execute business logic
            Object result =invoke(request);
            // Return result to client
            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(result);
            objectOutputStream.flush();
        } catch (IOException | ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }finally {
            if(objectInputStream! =null) {try {
                    objectInputStream.close();
                } catch(IOException e) { e.printStackTrace(); }}if(objectOutputStream! =null) {try {
                    objectOutputStream.close();
                } catch(IOException e) { e.printStackTrace(); }}}}private Object invoke(RpcRequest request) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        // Execute the method through reflection
        String className = request.getClassName();
        Object[] parameters = request.getParameters();
        Class[] types = new Class[parameters.length];
        for (int i = 0; i < parameters.length; i++) { types[i]=parameters[i].getClass(); } Class<? > aClass = Class.forName(className); Method method = aClass.getMethod(request.getMethodName(),types); Object result = method.invoke(service, parameters);returnresult; }}Copy the code

The Client side





JDK dynamic proxy



Client Service logic execution

package com.rpc.client;

import rpcservice.RpcRequest;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class RpcNetTransport {

    private String host;
    private int port;

    public RpcNetTransport(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public Object send(RpcRequest request){
        Object result = null;
        ObjectInputStream objectInputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            // The client requests the remote server
            Socket socket = new Socket(host, port);
            // Transfer data
            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(request);
            objectOutputStream.flush();
            
            // Receive the parameters returned by the Server
            objectInputStream = new ObjectInputStream(socket.getInputStream());
            result = objectInputStream.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            if(objectInputStream! =null) {try {
                    objectInputStream.close();
                } catch(IOException e) { e.printStackTrace(); }}if(objectOutputStream! =null) {try {
                    objectOutputStream.close();
                } catch(IOException e) { e.printStackTrace(); }}}returnresult; }}Copy the code