BIO application RPC framework

What is RPC?

  • RPC (Remote Procedure Call) is a technology that requests services from remote computer programs through the network without knowing the underlying network.

  • A complete RPC synchronous call process:
    1) The service consumer (client) calls the client stub in a local call mode;
    2) What is a client stub? That is, the local simulation object of the remote method also has method name and method parameters. After receiving the call, the client stub is responsible for wrapping the method name and method parameters, and sending the wrapped information to the server through the network;
    3) After receiving the message, the server gives it to the proxy stub and decodes it into the actual method name and parameters after the server part;
    4) server stub calls the local actual service on the server according to the decoding result;
    5) The local service executes and returns the result to the server stub;
    6) server stub packages the returned result into a message and sends it to the consumer;
    7) The client stub receives the message and decodes it;
    8) Service consumers get the final result.
  • The goal of RPC framework is to encapsulate all the intermediate steps, so that when we make a remote method call, it feels like calling locally.

RPC and HTTP

  • RPC literally means remote procedure call, which is just a description and an idea of calling each other between different applications. How to call it? The implementation method can be the most direct tcp communication or http. In many technical books on message oriented middleware, message oriented middleware is even used to realize RPC calls. As we know, dubbo is based on tcp communication, and gRPC is the open source software published by Google, based on the latest http2 0 protocol, the bottom layer uses the support of Netty framework. So to sum up, RPC and HTTP are two completely different levels of things, and there is no comparability between them.

Implement RPC framework

  • What problems need to be solved to implement RPC framework

Agency problem

  • What is the essence of agency to solve? The problem to be solved is that the called service is essentially a remote service, but the caller does not know or care. As long as the result is obtained, the specific thing is handled by the object of the proxy. Since it is a remote agent, of course, the agent mode should be used.

Serialization problem

  • What is the serialization problem in the computer? Our method calls have method names and method parameters. These may be strings or java classes defined by ourselves. However, when transmitting or saving on the network or hard disk, the network or hard disk does not recognize any strings or JavaBeans. It only recognizes binary 0 and 1 strings, so it needs to be serialized. After network transmission, it needs to make actual calls, It is necessary to change the binary 0 and 1 strings back to our actual java classes. This is called deserialization. java has provided us with the relevant mechanism Serializable.

Communication problems

  • We are using serialization to turn things into binary 0 and 1 strings that can be transmitted on the network, but how to transmit them through the network? Use the BIO provided by JDK for us.

Registered service instantiation

  • The registered service may be a name in our system. How to become an actual object instance, of course, is to use the reflection mechanism.

  • Reflection mechanism is to know all the attributes and methods of any class in the running state; For any object, you can call any of its methods and properties; This kind of dynamically obtained information and the function of dynamically calling the method of the object are called the reflection mechanism of java language.

  • The reflection mechanism mainly provides the following functions:
    1. Judge the class of any object at run time;
    2. Construct the object of any class at runtime;
    3. Judge the member variables and methods of any class at run time;
    4. Call the method of any object at run time;
    5. Generate dynamic proxy.

  • The following is a simple rpc framework. Complex functions such as load balancing, disaster recovery, clustering and disconnection reconnection are not realized.

Create registry

1. pom.xml

  • Use one of the simplest web projects

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>rpc-reg</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rpc-reg</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. properties

  • Set the port of the service, because there are server and client

server.port=8080

3. Startup class

package com.example.rpc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RpcRegApplication {

    public static void main(String[] args) {
        SpringApplication.run(RpcRegApplication.class, args);
    }

}

4. Registration center entity class

  • To implement the serialization interface

package com.example.rpc.remote.vo;

import java.io.Serializable;

//Registry entity
public class RegisterVO implements Serializable {
    private String host;
    private int port;

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

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

5. Registry implementation class

  • When the server starts, it registers its own information in the registry, and the client queries the server information when it starts

package com.example.rpc.service;

import com.example.rpc.remote.vo.RegisterVO;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//When the registration center of the client is started, when the registration center of the server is started
@Service
public class RegisterCenter {

    private static ExecutorService executorService =
            Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    //key represents the service name and value represents the collection of service addresses
    private static final Map<String, Set<RegisterVO>> serviceHoler = new HashMap<>();

    //Port number of the registration service
    private int port;

    //Service registration
    private static synchronized void registerService(String serviceName, String host, int port) {
        //Get the existing address collection of the current service
        Set<RegisterVO> voSet = serviceHoler.get(serviceName);
        if (voSet == null) {
            //If the existing address set is empty, a new set will be added
            voSet = new HashSet<>();
            serviceHoler.put(serviceName, voSet);
            System.out.println("Service registration succeeded," + serviceName + "," + host + ":" + port);
        }
        //Add the newly added service address to the collection
        voSet.add(new RegisterVO(host, port));
        System.out.println("Service address added successfully," + host + ":" + port);
    }

    //Remove service provider
    private static Set<RegisterVO> getService(String serviceName) {
        return serviceHoler.get(serviceName);
    }

    //Tasks for processing service requests: 1. Registering services; 2. Querying services
    private static class ServerTask implements Runnable {
        private Socket socket = null;

        public ServerTask(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try (ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
                 ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream())) {
                //Check whether the current request is registered or queried
                boolean isGetService = inputStream.readBoolean();
                //Query service
                if (isGetService) {
                    String serviceName = inputStream.readUTF();
                    //Fetch the address collection of the service provider
                    Set<RegisterVO> voSet = getService(serviceName);
                    //Return to client
                    outputStream.writeObject(voSet);
                    outputStream.flush();
                    System.out.println("Services to be queried-" + serviceName + "Send to client");
                }
                //Registration service
                else {
                    //Get the registered service name, ip, port
                    String serviceName = inputStream.readUTF();
                    String host = inputStream.readUTF();
                    int port = inputStream.readInt();
                    //Save in registry
                    registerService(serviceName, host, port);
                    outputStream.writeBoolean(true);
                    outputStream.flush();
                    System.out.println("Service registration succeeded:" + serviceName);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void startService() throws IOException {
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress(port));
        System.out.println("Registration Center on:" + port);
        try {
            while (true) {
                executorService.execute(new ServerTask(serverSocket.accept()));
            }
        } finally {
            serverSocket.close();
        }
    }

    //Start registry service
    @PostConstruct
    public void init() {
        this.port = 9001;
        new Thread(() -> {
            try {
                startService();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }

}

Create server

1. pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>rpc-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rpc-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. properties

server.port=8081

3. Startup class

package com.example.rpc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RpcServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(RpcServerApplication.class, args);
        System.out.println("hello world");
    }

}

4. Entity class of the message sent by the server

package com.example.rpc.remote.vo;

import java.io.Serializable;

public class UserInfo implements Serializable {
    private String name;
    private String phone;

    public UserInfo(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

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

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

5. Business methods provided externally

package com.example.rpc.remote;

import com.example.rpc.remote.vo.UserInfo;

public interface SendSms {

    //Send SMS
    boolean sendMsg(UserInfo userInfo);

}

6. Specific implementation of business methods

package com.example.rpc.sms;

import com.example.rpc.remote.SendSms;
import com.example.rpc.remote.vo.UserInfo;
import org.springframework.stereotype.Service;

//Implementation of SMS sending service
@Service
public class SendSmsImpl implements SendSms {
    @Override
    public boolean sendMsg(UserInfo userInfo) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("SMS sent to:" + userInfo.getName());
        return true;
    }
}

7. Complete service registration

package com.example.rpc.rpc.base;

import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

//Registration service
@Service
public class RegisterServiceWithRegCenter {

    //A list of locally available services, implemented with cache
    private static final Map<String, Class> serviceCache = new ConcurrentHashMap<>();

    //Register this service with the remote server and register this service locally at the same time
    public void regRemote(String serverName, String host, int port, Class impl) throws IOException {
        //Register with the registry
        Socket socket = new Socket();
        //Communication address of the server
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 9001);
        //Connect server
        socket.connect(inetSocketAddress);
        //Instantiate the input / output stream communicating with the client, output first and then input
        try (ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
             ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream())) {
            //false indicates the registration service, and true indicates the query service
            outputStream.writeBoolean(false);
            //Provide service name
            outputStream.writeUTF(serverName);
            //Provide ip
            outputStream.writeUTF(host);
            //Provide port
            outputStream.writeInt(port);
            outputStream.flush();
            //Receive the output of the server
            if (inputStream.readBoolean()) {
                System.out.println(serverName + "Service registration succeeded");
            }
            //The available services are put into the local cache
            serviceCache.put(serverName, impl);
        } finally {
            if (socket != null) {
                socket.close();
            }
        }
    }

    //Get service
    public Class getLocalService(String serviceName) {
        return serviceCache.get(serviceName);
    }

}

8. Server implementation

  • Support remote procedure call and provide business methods

package com.example.rpc.rpc.base;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//Server
@Service
public class RpcServerFrame {

    private static ExecutorService executorService =
            Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    @Autowired
    private RegisterServiceWithRegCenter registerServiceWithRegCenter;

    //Process service request task
    private static class ServerTask implements Runnable {

        private Socket socket;

        private RegisterServiceWithRegCenter registerServiceWithRegCenter;

        public ServerTask(Socket socket, RegisterServiceWithRegCenter registerServiceWithRegCenter) {
            this.socket = socket;
            this.registerServiceWithRegCenter = registerServiceWithRegCenter;
        }

        @Override
        public void run() {
            try (ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
                 ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream())) {
                //Class name of the method
                String serviceName = inputStream.readUTF();
                //Method name
                String methodName = inputStream.readUTF();
                //Input parameter type of method
                Class<?>[] paramTypes = (Class<?>[]) inputStream.readObject();
                //Input parameter value of method
                Object[] args = (Object[]) inputStream.readObject();

                //Get the class object of the service from the container
                Class serviceClass = registerServiceWithRegCenter.getLocalService(serviceName);
                if (serviceClass == null) {
                    throw new ClassNotFoundException(serviceName + "not found");
                }
                //Execute the actual method through reflection
                Method method = serviceClass.getMethod(methodName, paramTypes);
                Object result = method.invoke(serviceClass.newInstance(), args);
                //Returns the execution result of the service to the caller
                outputStream.writeObject(result);
                outputStream.flush();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void startService(String serverName, String host, int port, Class impl) throws Throwable {
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress(port));
        System.out.println("server is on :" + port);
        registerServiceWithRegCenter.regRemote(serverName, host, port, impl);
        try {
            while (true) {
                executorService.execute(new ServerTask(serverSocket.accept(), registerServiceWithRegCenter));
            }
        } finally {
            serverSocket.close();
        }
    }

}

9. Start service

package com.example.rpc.sms;

import com.example.rpc.remote.SendSms;
import com.example.rpc.rpc.base.RpcServerFrame;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Random;

//The server of rpc provides services
@Service
public class SmsRpcServer {
    @Autowired
    private RpcServerFrame rpcServerFrame;

    @PostConstruct
    public void server() {
        Random random = new Random();
        int port = 8888 + random.nextInt(100);
        try {
            //Register this service with the remote server and provide business classes
            rpcServerFrame.startService(SendSms.class.getName(), "127.0.0.1", port, SendSmsImpl.class);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

}

Create client

1. pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>rpc-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rpc-client</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. properties

server.port=8082

3. Startup class

package com.example.rpc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RpcClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(RpcClientApplication.class, args);
    }

}

4. Class of stub remote service

  • If you want to use the method on the remote service as you want to use the method in your own project, you must use the local stub

  • The stub here needs to include the entity class RegisterVO of the registry, which is the same as the code of the registry project

package com.example.rpc.remote.vo;

import java.io.Serializable;

//Registry entity
public class RegisterVO implements Serializable {
    private String host;
    private int port;

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

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

  • The entity class UserInfo of the server

package com.example.rpc.remote.vo;

import java.io.Serializable;

public class UserInfo implements Serializable {
    private String name;
    private String phone;

    public UserInfo(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

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

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

  • Interface for sending information at the server

package com.example.rpc.remote;


import com.example.rpc.remote.vo.UserInfo;

public interface SendSms {

    //Send SMS
    boolean sendMsg(UserInfo userInfo);

}

  • It should be noted here that the fully qualified name of the local stub class should be consistent with the fully qualified name of the remote class, otherwise you will not find it when you get the class through reflection on the server. For example, the fully qualified name of the following class is com.com on the client and server example. rpc. remote. SendSms


5. Client implementation

  • Method of calling remote service through dynamic proxy

package com.example.rpc.client.rpc;

import com.example.rpc.remote.vo.RegisterVO;
import org.springframework.stereotype.Service;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;

//Client agent part
@Service
public class RpcClientFrame {
    //Get the address list of the service provider
    private static List<InetSocketAddress> getAddressList(String serviceName) throws Exception {
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress("127.0.0.1", 9001));
        try (ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
             ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream())) {
            //Query service list
            outputStream.writeBoolean(true);
            //Send service name
            outputStream.writeUTF(serviceName);
            outputStream.flush();
            Set<RegisterVO> voSet = (Set<RegisterVO>) inputStream.readObject();
            List<InetSocketAddress> services = new ArrayList<>();
            for (RegisterVO registerVO : voSet) {
                String host = registerVO.getHost();
                int port = registerVO.getPort();
                InetSocketAddress address = new InetSocketAddress(host, port);
                services.add(address);
            }
            System.out.println("Query service list succeeded:" + serviceName);
            return services;

        } finally {
            if (socket != null) {
                socket.close();
            }
        }
    }

    //Gets the address of the remote service
    private static InetSocketAddress getService(String serviceName) throws Exception {
        Random random = new Random();
        //Get the address list of the service provider
        List<InetSocketAddress> addressList = getAddressList(serviceName);
        //Choose one at random
        InetSocketAddress address = addressList.get(random.nextInt(addressList.size()));
        System.out.println("The server selected for this call is:" + address);
        return address;
    }

    //Dynamic proxy to access remote services
    private static class DynProxy implements InvocationHandler {
        private Class<?> serviceInterface;
        private InetSocketAddress socketAddress;

        public DynProxy(Class<?> serviceInterface, InetSocketAddress socketAddress) {
            this.serviceInterface = serviceInterface;
            this.socketAddress = socketAddress;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Socket socket = new Socket();
            socket.connect(socketAddress);
            try (ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
                 ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream())) {
                //The name of the class in which the method is located
                outputStream.writeUTF(serviceInterface.getName());
                //Method name
                outputStream.writeUTF(method.getName());
                //Method input parameter type
                outputStream.writeObject(method.getParameterTypes());
                //Method input parameter
                outputStream.writeObject(args);
                outputStream.flush();
                //Receive server output
                System.out.println(serviceInterface + "remote exec success !");
                return inputStream.readObject();
            } finally {
                if (socket != null) {
                    socket.close();
                }
            }
        }
    }

    //The proxy object of the remote service. The parameter is the service to be called by the client
    public static Object getRemoteProxyObject(Class serviceInterface) throws Exception {
        //Get a network address for the remote service
        InetSocketAddress address = getService(serviceInterface.getName());
        //Get a proxy object, and the proxy object makes the actual service call through the network
        return Proxy.newProxyInstance(serviceInterface.getClassLoader(),
                new Class[]{serviceInterface}, new DynProxy(serviceInterface, address));
    }

}

6. bean injected into remote service

  • Add SendSms to the spring container through @ Bean. SendSms is actually a proxy object

package com.example.rpc.client.config;

import com.example.rpc.client.rpc.RpcClientFrame;
import com.example.rpc.remote.SendSms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ClientConfig {

    @Autowired
    private RpcClientFrame rpcClientFrame;

    //Inject the SendSms class of the remote service, and you can use the methods in the controller
    @Bean
    public SendSms getSendSms() throws Exception {
        return (SendSms) rpcClientFrame.getRemoteProxyObject(SendSms.class);
    }
}

7. Create Controller

  • It is used to call the method of sending information in the server SendSms class

package com.example.rpc.Controller;

import com.example.rpc.remote.SendSms;
import com.example.rpc.remote.vo.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ClientController {

    @Autowired
    private SendSms sendSms;

    @RequestMapping(value = "sendMsg")
    public void sendMsg() {
        long start = System.currentTimeMillis();
        UserInfo userInfo = new UserInfo("fisher", "123456");
        System.out.println("send message: " + sendSms.sendMsg(userInfo));
        System.out.println("Total time:" + (System.currentTimeMillis() - start) + "ms");
    }
}

8. Start the service and view the test results

  • Start the registry first, then the server, and finally the client

  • The registration function uses port 9001. After starting the server, the server address 127.0.0.1:8940 is successfully registered in the registration center. Finally, start the client, and the client will query the service list in the registration center
  • request http://localhost:8082/sendMsg

  • Client printing

  • Server printing

Code download address

https://gitee.com/fisher3652/netWork.git

Tags: network Network Protocol

Posted by sanfly on Mon, 09 May 2022 07:56:03 +0300