3-1-3 (Part 1) Distributed Architecture Network Communication

1. Distributed architecture network communication

In the distributed service framework, one of the most basic questions is how remote services communicate. There are many technologies that can realize remote communication in the Java field, such as RMI, Hessian, SOAP, ESB, and JMS. What is behind them? What principle is it based on?

1.1. Basic principles

To realize the communication between network machines, we must first look at the basic principles of computer system network communication. At the bottom level, what network communication needs to do is to transfer the stream from one computer to another, based on the transmission protocol and Network IO is realized. Among them, the transmission protocols are more well-known such as tcp, udp, etc., tcp, udp are all based on the concept of Socket extended for certain types of application scenarios, network IO, mainly bio, nio, aio In the three ways, all distributed application communication is implemented based on this principle, just for the ease of use of the application. Various languages ​​usually provide some application layer protocols that are closer to the application and are easier to use.

Insert picture description here

1.2 What is RPC

The full name of RPC is remote procedure call, that is, remote procedure call.
With the help of RPC, remote services can be called like local calls, which is an inter-process communication method

For example, two servers A and B. One application is deployed on server A and one application is deployed on server B. The application on server A wants to call the method provided by the application on server B. Since the two applications are not in the same memory space, they cannot be called directly. , So it is necessary to express the semantics of the call and convey the data of the call through the network.

It should be noted that RPC is not a specific technology, but refers to the entire network remote call process.

RPC architecture
A complete RPC architecture contains four core components, namely Client, Client Stub, Server and Server Stub. This Stub can be understood as a stub.

  • Client, the caller of the service.
  • The client stub (Client Stub) stores the address message of the server, and then packages the client's request parameters into a network message, and then sends it to the server remotely through the network.
  • Server, the real service provider.
  • The server stub receives the message sent by the client, unpacks the message, and calls the local method.

Insert picture description here

Insert picture description here

(1) The client calls the service locally (that is, by way of interface);
(2) After receiving the call, the client stub is responsible for assembling methods, parameters, etc. into a network capable of transmission Message body (serialize the message body object into binary);
(3) The client sends the message to the server through sockets;
(4) The server stub decodes the message after receiving the message (deserializes the message object) );
(5) The server stub calls the local service according to the decoding result;
(6) The local service executes and returns the result to the server stub;
(7) The server stub will The returned result is packaged into a message (the result message object is serialized);
(8) The server sends the message to the client through sockets;
(9) The client stub receives the result message and decodes it ( Serialize the result message);
(10) The client gets the final result.
The goal of RPC is to encapsulate the steps 2, 3, 4, 7, 8, and 9.
Note: No matter what type of data, it needs to be converted into a binary stream for transmission on the network. The sender of the data needs to convert the object to a binary stream, and the receiver of the data needs to restore the binary stream to an object.
There are many RPC frameworks in java. Common ones include Hessian, gRPC, Thrix, HSF (High Speed ​​Service Framework), Dubbo, etc. In fact, for the RPC framework, the core module is communication and serialization.

Two, RMI

2.1. Introduction

Java RMI refers to the remote method invocation (Remote Method Invocation), which is the remote invocation natively supported by java. It uses JRMP (Java Remote Messageing protocol) as the communication protocol. It can be considered as a pure java version of the distributed remote invocation solution. RMI mainly It is used for communication between different virtual machines. These virtual machines can be on different hosts or on the same host. The communication here can be understood as a method for an object on one virtual machine to call an object on another virtual machine.

1. Client:
1) Stub: the proxy of the remote object on the client;
2) Remote Reference Layer: parse and execute the remote reference protocol;
3) Transport: send Invoke, pass remote method parameters, and receive remote method execution results.

2. Server:
1) Skeleton: Read the method parameters passed by the client, call the actual object method of the server, and receive the return value after the method is executed;
2) Remote Reference Layer: Processing Send remote method calls to the skeleton after remote reference;
3) Transport layer (Transport): monitor the client's inbound connection, receive and forward the call to the remote reference layer.

3. Registry (Registry): Register the remote object in the form of URL, and reply to the client the reference to the remote object.

Insert picture description here
Remote call process:

1) The client queries and obtains remote object references from the registry of the remote server.
2) The stub object and the remote object have the same interface and method list. When the client calls the remote object, it is actually completed by the corresponding stub object proxy.
3) The remote reference layer converts the local reference of the stub to the remote reference of the object on the server, and then passes the call to the Transport (Transport), and the transport layer sends the call through the TCP protocol;
4) On the server side, the transport layer listens to incoming calls. Station connection, once it receives the client remote call, it forwards the reference to the upper remote reference layer;
5) The server-side remote reference layer converts the remote application sent by the client into the reference of the local virtual machine. Pass the request to the skeleton (Skeleton);
6) The skeleton reads the parameters, then passes the request to the server, and finally the server makes the actual method call

Results return process:

1) If there is a return value after the remote method call, the server will pass these results down the "skeleton -> remote reference layer -> transport layer"; 2) After the client's transport layer receives the return value, it will follow "Transport layer -> remote reference layer -> stub" is passed up, and then the stub will deserialize these return values ​​and pass the final result to the client program.

2.2 Development process

1. Server:

1) Define the Remote sub-interface, define the remote methods to be published within it, and these methods must be Throws RemoteException;
2) Define the implementation of the remote interface, and inherit: UnicastRemoteObject
3) Start the server: complete the startup of the registry and the remote object in turn Binding.

2. Client:

1) Obtain from the registry through a URL string conforming to JRMP specifications and force it into a Remote sub-interface object;
2) Invoking a method in this Remote sub-interface object is a remote method invocation behavior.

2.3 Code implementation

2.3.1 Common code for server and client

  1. Create remote interface

import com.lagou.entity.User;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 * 远程服务对象接口必须继承Remote接口;同时方法必须抛出RemoteExceptino异常
 */
public interface Hello extends Remote {
    
    

    public String sayHello(User user) throws RemoteException;
    
}


  1. Which has a reference object as a parameter
import java.io.Serializable;

/** * 引用对象应该是可序列化对象,这样才能在远程调用的时候:
 * 1. 序列化对象
 * 2. 拷贝
 * 3. 在网络中传输 *
 * 4. 服务端反序列化
 * 5. 获取参数进行方法调用;
 * 这种方式其实是将远程对象引用传递的方式转化为值传递的方式 */
public class User implements Serializable {
    
    
    private String name;
    private int age;

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }
}


  1. Realize remote service objects
import com.lagou.entity.User;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
 * 远程服务对象实现类写在服务端;必须继承UnicastRemoteObject或其子类
 **/
public class HelloImpl extends UnicastRemoteObject implements Hello {
    
    

    private static final long serialVersionID =  3638546195897885959L;

    /** 
     * 因为UnicastRemoteObject的构造方法抛出了RemoteException异常,
     * 因此这里默认的构造方法必须写,必须声明 抛出RemoteException异常
     * @throws RemoteException 
     */
    protected HelloImpl() throws RemoteException {
    
    
    }

    @Override
    public String sayHello(User user) throws RemoteException {
    
    

        System.out.println("this is server,hello " + user.getName());

        return "success";
    }
}

2.3.2 Server code

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;

/**
 * 服务端的程序
 */
public class Server {
    
    

    public static void main(String[] args) {
    
    
        try {
    
    

            // 创建一个远程对象,同时也胡创建一个stud对象,skeleton 对象
            Hello hello = new HelloImpl();

            // 本地主机上的远程对象注册表registry的实例,并指定端口为 8888 ,这一步 必不可少(java 默认端口是1099)
            // 必不可缺的一步,缺少注册表创建,则无法 绑定对象到远程 注册表上
            LocateRegistry.createRegistry(8080);  // 启动注册服务

            try {
    
    
                Naming.bind("//127.0.0.1:8080/zm",hello);
            }catch (Exception e){
    
    
                e.printStackTrace();
            }
            System.out.println("service bind already!!");
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }

}

2.3.3 Client code

import com.lagou.entity.User;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

public class Client {
    
    

    public static void main(String[] args) {
    
    
        try {
    
    
            Hello hello = (Hello)Naming.lookup("//127.0.0.1:8080/zm");

            User user = new User();
            user.setName("james");
            System.out.println(hello.sayHello(user));

        } catch (NotBoundException e) {
    
    
            e.printStackTrace();
        } catch (MalformedURLException e) {
    
    
            e.printStackTrace();
        } catch (RemoteException e) {
    
    
            e.printStackTrace();
        }
    }

}


Guess you like

Origin blog.csdn.net/qq_42082278/article/details/113174567