Hand-tear RPC implementa una implementación simple tipo Dubbo basada en TCP

Implementación RPC manual de implementación dubbo basada en TCP

Recuerdo la primera vez que escuché esta palabra en el video de la entrevista de alguien. Después de un breve entendimiento, solo supe que era una llamada remota.
Nunca imaginé que la primera pregunta de mi primera entrevista estaba relacionada con esto. Espero prepararme para cada entrevista seriamente y oportunamente para ver si hay vacantes y llenar vacantes.

Idea:
my-rpc llama a la interfaz al servidor a través del cliente

Inserte la descripción de la imagen aquí

Efecto de llamada al método

Inserte la descripción de la imagen aquí

Submódulo

Inserte la descripción de la imagen aquí

Interfaz de escritura

Serialización y codificación unificada

Inserte la descripción de la imagen aquí
Ejemplos e interfaces
Inserte la descripción de la imagen aquí

Socket logra por RPC, la dependencia del módulo de coordinación entre la atención
implementado primer servidor
servidor: método implementado se basa instancia de objeto de interfaz de
cliente: UserInfoService.class basa interfaz proporciona
myrpc: la necesidad de que el cliente, el servidor proporciona servicios

El cliente se escribe a través del proxy

Inserte la descripción de la imagen aquí

Ejecute la
conexión de prueba rechazada porque el servicio remoto no ha abierto
java.net.ConnectException: conexión rechazada (conexión rechazada)

Escribir servidor, ajustar rpc en paralelo

Recuerda siempre mantener tcp bajo la reflexión, agente

Implementación de código

myRpc

ServerHandler

package com.bennyrhys.handler;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 对服务端的请求处理
 * @Author bennyrhys
 * @Date 2020-03-22 09:58
 */
public class ServerHandler {
    /**
     * 对请求的处理
     * @param target
     * @param port
     */
    public void handel(Object target, int port) {
        try {
            // 接收后端连接
            ServerSocket serverSocket = new ServerSocket(port);

            while (true) {
                // 阻塞方法
                Socket socket = serverSocket.accept();

                // 运行一个线程
                // 接收远程请求,对请求进行处理
                new Thread(new ServiceProcess(socket, target)).start();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Proceso de servicio

package com.bennyrhys.handler;

import com.bennyrhys.request.RpcRequest;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.Socket;

/**
 * 线程服务的处理
 * @Author bennyrhys
 * @Date 2020-03-22 10:04
 */
public class ServiceProcess implements Runnable {

    private Socket socket;
    // 目标对象,也就是UserServiceImpl
    private Object target;

    public ServiceProcess(Socket socket, Object target) {
        this.socket = socket;
        this.target = target;
    }



    public void run() {

        try {
            // 拿到客户端发送来的数据
            InputStream is = socket.getInputStream();
            // 包装成对象输入流
            ObjectInputStream ois = new ObjectInputStream(is);
            // 拿到客户端封装的对象
            RpcRequest rpcRequest =  (RpcRequest)ois.readObject();

            // 开始调用service实现-反射
            Object obj = invoke(rpcRequest);

            OutputStream os = socket.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(os);
            oos.writeObject(obj);
            oos.flush();

            os.close();
            oos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 实现对UserServiceImpl方法getUserInfo()的调用
     * @param rpcRequest
     * @return
     */
    public Object invoke(RpcRequest rpcRequest) {

        String methodName = rpcRequest.getMethodName();
        Object[] parameters = rpcRequest.getParameters();

        Class[] parameterTypes = new Class[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            parameterTypes[i] = parameters[i].getClass();
        }
        
        try {
            Method  method = target.getClass().getDeclaredMethod(methodName, parameterTypes);
            // 反射调用 目标对象,方法参数
            // methed 代表getUserInfo()方法的反射方法java.long.reflect.Method信息
            // invoke 代表调用getUserInfo()
            // target 你现在要调哪个对象的getUserInfo()方法,要调UserServiceImpl对象,target代表UserServiceImpl的方法
            // parameters 代表getUserInfo()方法的参数,如果方法没有参数,那么就null
            Object obj = method.invoke(target, parameters);
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

MyInvocationHandler

package com.bennyrhys.proxy;

import com.bennyrhys.request.RpcInvoke;
import com.bennyrhys.request.RpcRequest;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 实现InvocationHandler接口
 * 调用getProxyObject方法的时候,会被该invoke拦截
 * @Author bennyrhys
 * @Date 2020-03-22 00:15
 */
public class MyInvocationHandler implements InvocationHandler {

    private String ip;
    private int port;

    public MyInvocationHandler(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    /**
     *
     * @param proxy --> 代理类。也就是UserService的代理类
     * @param method --> getUserInfo()
     * @param args --> getUserInfo()方法的参数
     * @return
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 实现对远程方法的调用,先准备数据
        System.out.println("远程调用在此处拦截,进行数据封装");

        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        // 封装的对象
        // 避免空指针
        RpcRequest rpcRequest = new RpcRequest(className, methodName, args == null ? new Object[]{} : args);

        // 调用远程方法
        RpcInvoke rpcInvoke = new RpcInvoke(ip, port);
        return rpcInvoke.invoke(rpcRequest);

    }
}

RpcProxy

package com.bennyrhys.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * rpc代理类
 * @Author bennyrhys
 * @Date 2020-03-22 00:05
 */
public class RpcProxy {

    @SuppressWarnings("unchecked")
    public <T> T getProxyObject(Class<T> classInterFaces, String ip, int port) {
        // 使用JDK去实现动态代理
        return (T)Proxy.newProxyInstance(classInterFaces.getClassLoader(),
                new Class<?>[] {classInterFaces},
                new MyInvocationHandler(ip, port));
    }
}

rpc-client

package com.bennyrhys;

import com.bennyrhys.model.UserInfo;
import com.bennyrhys.proxy.RpcProxy;
import com.bennyrhys.service.UserInfoService;

/**
 * 客户端获取
 * @Author bennyrhys
 * @Date 2020-03-21 23:20
 */
public class client {

    private static final String IP = "127.0.0.1";
    private static final int PORT = 12345;

    public static void main(String[] args) {

        // rpc代理
        RpcProxy proxy = new RpcProxy();

        // 如果拿到UserInfoService的实现类(代理技术)
        UserInfoService userInfoService = proxy.getProxyObject(UserInfoService.class, IP, PORT);
        UserInfo user = userInfoService.getUserInfo();
        System.out.println(user);
    }
}

interfaz rpc

package com.bennyrhys.model;

import java.io.Serializable;

/**
 * @Author bennyrhys
 * @Date 2020-03-21 23:04
 */
// Tcp网络传输,要变为序列化
public class UserInfo implements Serializable {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "UserInfo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

UserInfoService

package com.bennyrhys.service;

import com.bennyrhys.model.UserInfo;

/**
 * @Author bennyrhys
 * @Date 2020-03-21 22:47
 */
public interface UserInfoService {
    public UserInfo getUserInfo();
}

servidor rpc

UserServiceImpl

package com.bennyrhys.service.impl;

import com.bennyrhys.model.UserInfo;
import com.bennyrhys.service.UserInfoService;

/**
 * 实现用户接口
 * 通过添加依赖
 * @Author bennyrhys
 * @Date 2020-03-21 23:23
 */
public class UserServiceImpl implements UserInfoService {
    public UserInfo getUserInfo() {
        // 写死-假设数据库拿到数据
        UserInfo user = new UserInfo();
        user.setId(10086);
        user.setName("查询");
        return user;
    }
}

Servidor

package com.bennyrhys;

import com.bennyrhys.handler.ServerHandler;
import com.bennyrhys.service.impl.UserServiceImpl;

import java.net.ServerSocket;

/**
 * 服务端接收
 * @Author bennyrhys
 * @Date 2020-03-22 09:48
 */
public class Server {
    public static void main(String[] args) {
        ServerHandler serverHandler = new ServerHandler();
        // new UserServiceImpl(),可以用注册中心写活, 端口和客户端给定的一样
        serverHandler.handel(new UserServiceImpl(), 12345);
    }
}

Código fuente

Subido, la mina asincrónica oficial invitada, descarga el área de recursos

234 artículos originales publicados · Me gusta 164 · Visitas 140,000+

Supongo que te gusta

Origin blog.csdn.net/weixin_43469680/article/details/105026797
Recomendado
Clasificación