Implement RPC service call framework by yourself

Keywords: Java socket Programming JDK

Reprint

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);
    }
}

Posted by wiggst3r on Wed, 01 Jan 2020 00:37:47 -0800