RPC (simple implementation)



RPC only seen this word before I totally did not understand before, finally did not want to run into. Cause: here want to improve concurrency and see kafka (final compromise uses redis), which kafka need to install ZooKeeper, and ZooKeeper and related distributed, and then continue to discover distributed is based on RPC, then wrote this blog


1. RPC

RPC (Remote Procedure Call) Remote Procedure Call, namely to call the service on a remote computer through a network of communication, and this process is like calling a local method call is as simple and transparent, and does not require technical knowledge of the underlying network protocol. RPC uses C / S architecture, the program is requesting Client, Server is to provide services, similar to the Http request and response. Conclusion is simple: the actual method call in the remote, but like as simple as calling a local method.


1) For the clients that I am: a call to the local method (stub) will be able to obtain services. This stub is a proxy remote services, how its underlying implementation, for me, is transparent.

2) For remote server: Is there a way to connect up listening to on the call and corresponding return (the server easier to understand)


Its structure is as follows:

  1. Users call a "local" function, which handles customer calls (stub remote service locally)
  2. Handle customer calls the communication network to access remote programs
  3. Remote program receives network traffic and related information to call the service handle
  4. Service Handle calls the service function, the function returns the result to complete a reverse end remote call








2. Why do you need RPC

When our ever-growing volume of business, the role of the number of vertical add servers to improve the performance of micro almost even more, this time there will inevitably be a distributed architecture to better improve performance. Each service distributed architecture are separate parts, and when it is necessary to complete a business relies upon a different type of service, these services need to call each other, this time between the call service is a need for an efficient application of between means of communication, and this is why the emergence of PRC








3. RPC implementation requirements


3.1 Service Provider

Service: implement the services provided

Services storm drain: just realized the service is not enough, you also need to provide the service storm drain to the outside world, let the outside world know what, how to use the service


3.2 Service caller

Remote proxy object: when calling the native method call is actually a remote method, it is bound to local needs a remote proxy object


Summary: In order to implement an RPC requires: communication model (BIO, NIO), service location (IP, PORT), the remote proxy object (remote service local proxy), serialized (converted into binary transmission network)





4. simple implementation

Its main clients are: server interfaces, server interface, storm drain services, client interface (and server share the same interfaces), reference services


4.1 server interfaces

public interface Service {

    // 提供两个服务,说hello和整数相加
    public String hello();
    public int sum(int a, int b);
    
}


4.2 server interface

public class ServiceImpl implements Service {

    @Override
    public String hello() {
        return "Hello World";
    }

    @Override
    public int sum(int a, int b) {
        return  a + b;
    }
}


4.3 Service storm drain

public static void export(Object service, int port) {
    
    if (service == null || port <= 0 || port > 65535) {
        throw new RuntimeException("Arguments error");
    }
    
    System.out.println(service.getClass().getName() + ": " + port + "服务暴露");
    
    new Thread( () -> {
        
        try (ServerSocket server = new ServerSocket(port);) {
            
            while(true){
                try (
                        Socket socket = server.accept();
                        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
                        ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
                    ) {
                    
                    // 读取方法名
                    String methodName = in.readUTF();
                    
                    // 读取参数类型
                    Class<?>[] parameterTypes = (Class<?>[])in.readObject();
                    
                    // 读取参数值
                    Object[] arguments = (Object[])in.readObject();
                    
                    // 获取方法
                    Method method = service.getClass().getMethod(methodName, parameterTypes);
                    
                    // 处理结果
                    Object result = method.invoke(service, arguments);
                    
                    // 写入结果
                    out.writeObject(result);
                    
                } catch (Exception e) {
                    e.printStackTrace();
                } 
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }).start();
}

This logic is exposed server monitor specific ports, such as the client initiated the request after the connection, and then get the method name, parameters, and other related information through the Java IO streams, and finally by the reflection method calls and the results achieved in response to the client


4.4 Client Interface

public interface ClientService {

    // 提供两个服务,说hello和整数相加
    public String hello();
    public int sum(int a, int b);
        
}


4.5 Service Reference

public static <T>T refer(Class<T> interfaceClass, String host, int port){
    
    if(interfaceClass == null || !interfaceClass.isInterface() || host == null || port <= 0 || port > 65535){
        throw new RuntimeException("Arguments error");
    }
    
    System.out.println("正在调用远程服务");
    
    @SuppressWarnings("unchecked")
    T proxy = (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {
                
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            
            Object result = null;
            try (
                    Socket socket = new Socket(host, port);
                    ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
                    ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
                ) {
                
                out.writeUTF(method.getName());
                
                out.writeObject(method.getParameterTypes());
                
                out.writeObject(args);
                
                result = in.readObject();
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    });
    return proxy;
}

The service logic is cited: Create the Socket connection, the sequence of the relevant request information to the server, and then waits for a response result. Which is transparent calls using dynamic proxies


4.6 Test

public class Test {
    
    public static void main(String[] args) {
        
        // 暴露服务
        ServiceImpl service = new ServiceImpl();
        RPCFramework.export(service, 8080);
        
        // 调用服务
        Client client = RPCFramework.refer(Client.class, "127.0.0.1", 8080);
        int sum = client.sum(1, 2);
        String rs = client.hello();
        System.out.println("远程响应:" + sum);
        System.out.println("远程响应:" + rs);
    }
}
RPC.ServiceImpl:8080----- 服务暴露

正在调用远程服务
远程响应:3
远程响应:Hello World






5. Thinking


Why not Http 5.1

Independent of the specific RPC protocol, based on the Http, TCP, but TCP performance because of relatively good. Http application layer protocol, TCP transport layer protocol belongs, relatively less in the bottom layer of the package, and reliable transmission for selecting does not select UDP TCP


5.2 RPC common framework

Dubbo (Ali Baba), SpringCloud, RMI (JDK built-in)


5.3 Why use dynamic proxies

Because to be like a local call, it is transparent to the user.

Object result = XXX(String method, String host, int port)

In fact, above this line, but it does not feel the same way as a local call, and if there is more than one interface method, then called once every method you need to send a host / port

// 动态代理可以这样使用
ProxyObject.方法1
ProxyObject.方法2

// 没有使用动态代理则不人性化
XXX(String method1, String host, int port)
XXX(String method2, String host, int port)


5.4 Why the need for separate types of parameters and parameter transfer

In order to facilitate overload resolution method, the following method name and method for obtaining required parameter types

service.getClass().getMethod(methodName, parameterTypes)






6. Optimization


6.1 Network Communications

The above examples used in the form of BIO, resulting in obstruction of concurrent access is not high, may be replaced with NIO


6.2 Serialization

JDK used herein the native sequence of the method can only be achieved Serializable class interface, third party libraries can be used to improve performance


6.3 Service load

Auto-discovery service, a client can dynamically perceive changes in the server, from the heat to achieve deployment, the timing of the polling of the available methods, eg: ZooKeeper


6.4 Cluster

Clusters, so that it can provide load balancing


6.5 request and response

Requests and responses may be encoded package, rather than sending a single such








Guess you like

Origin www.cnblogs.com/Howlet/p/12367745.html