RPC学习

RPC

远程过程调用

服务提供者 将服务提供到注册中心,消费者从注册中心获取需要i调用的服务,去进行调用

模块创建

消费者(Consumer)

** pom **

java 复制代码
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>rpc01</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>Consumer</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>ProviderCommon</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>ycrpc</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

** 代码**

java 复制代码
package com.yc;

import com.yc.common.Invocation;
import com.yc.protocol.HttpClient;
import com.yc.proxy.ProxyFactory;

/**
 * @Author yc
 * @PackageName yeb
 * @Package com.yc
 * @Date 2023/9/5 17:05
 */
public class Consumer {

    public static void main(String[] args) {
//        HelloService helloService = ProxyFactory.getProxy(HelloService.class);
        HelloService helloService = ProxyFactory.getProxy(HelloService.class);
        String result = helloService.sayHello("yc1111");
        System.out.println(result);


    }


}
提供者(Provider)

** pom **

java 复制代码
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>rpc01</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>Provider</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>ProviderCommon</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>ycrpc</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

** 代码 **

java 复制代码
package com.yc;


import com.yc.common.URL;
import com.yc.protocol.HttpServer;
import com.yc.register.LocalRegister;
import com.yc.register.MapRemoteRegister;

/**
 * @Author yc
 * @PackageName yeb
 * @Package com.yc
 * @Date 2023/9/5 17:11
 */
public class Provider {

    public static void main(String[] args) {

        LocalRegister.regist(HelloService.class.getName(),"1.0",HelloServiceImpl.class);
//        LocalRegister.regist(HelloService.class.getName(),"1.0",HelloServiceImpl02.class);

        //注册中心注册,服务注册
        URL url = new URL("127.0.0.1",8181);
        MapRemoteRegister.regist(HelloService.class.getName(),url);

        HttpServer httpServer = new HttpServer();
        httpServer.start(url.getHostname(),url.getPort());





    }
}
ProviderCommon


** pom **

java 复制代码
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>rpc01</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ProviderCommon</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>
rpc

** pom **

java 复制代码
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>rpc01</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ycrpc</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.93</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>
    </dependencies>

</project>
启动tomcat
java 复制代码
package com.yc.protocol;

import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.Tomcat;

/**
 * @Author yc
 * @PackageName yeb
 * @Package com.yc.protocol
 * @Date 2023/9/5 17:20
 */
public class HttpServer {

    public void start(String hostName,Integer prot ){

        Tomcat tomcat = new Tomcat();

        Server server = tomcat.getServer();
        Service service = server.findService("Tomcat");

        Connector connector = new Connector();
        connector.setPort(prot);

        StandardEngine engine = new StandardEngine();
        engine.setDefaultHost(hostName);

        StandardHost host = new StandardHost();
        host.setName(hostName);

        String contextPath="";
        StandardContext context = new StandardContext();
        context.setPath(contextPath);
        context.addLifecycleListener(new Tomcat.FixContextListener());

        host.addChild(context);
        engine.addChild(host);

        service.setContainer(engine);
        service.addConnector(connector);

        tomcat.addServlet(contextPath,"dispatcher",new DisPatcherServlet());
        context.addServletMappingDecoded("/*","dispatcher");

        try {
            tomcat.start();
            tomcat.getServer().await();
        } catch (Exception e) {
          e.printStackTrace();
        }

    }

}
DisPatcherServlet
java 复制代码
package com.yc.protocol;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import java.io.IOException;

/**
 * @Author yc
 * @PackageName rpc01
 * @Package com.yc.protocol
 * @Date 2023/9/6 14:09
 */
public class DisPatcherServlet extends HttpServlet {

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        new HttpServerHandler().handler(req,res);
    }
}
HttpServerHandler
java 复制代码
package com.yc.protocol;

import com.yc.common.Invocation;
import com.yc.register.LocalRegister;
import org.apache.commons.io.IOUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.ObjectInputStream;
import java.lang.reflect.Method;

/**
 * @Author yc
 * @PackageName rpc01
 * @Package com.yc.protocol
 * @Date 2023/9/6 14:11
 */
public class HttpServerHandler {


    public void handler(ServletRequest req, ServletResponse res) {
        // 处理请求 --》 接口、方法、方法参数

        try {
            Invocation invocation = (Invocation) new ObjectInputStream(req.getInputStream()).readObject();
            String interfaceName = invocation.getInterfaceName();
            Class classImpl = LocalRegister.get(interfaceName, "1.0");
            Method method = classImpl.getMethod(invocation.getMethodName(), invocation.getParameterTypes());
            String result = (String) method.invoke(classImpl.newInstance(), invocation.getParameters());

            IOUtils.write(result, res.getOutputStream());

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


    }
}
Invocation(调用对象)
java 复制代码
package com.yc.common;

import java.io.Serializable;

/**
 * @Author yc
 * @PackageName rpc01
 * @Package com.yc.common
 * @Date 2023/9/6 14:13
 */
public class Invocation implements Serializable {

    private String interfaceName; //接口名
    private String methodName; //方法名
    private Class[] parameterTypes;//参数类型
    private Object[] parameters;//参数

    public Invocation(String interfaceName, String methodName,  Class[] parameterTypes, Object[] parameters) {
        this.interfaceName = interfaceName;
        this.methodName = methodName;
        this.parameterTypes = parameterTypes;
        this.parameters = parameters;
    }

    public String getInterfaceName() {
        return interfaceName;
    }

    public void setInterfaceName(String interfaceName) {
        this.interfaceName = interfaceName;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Class[] getParameterTypes() {
        return parameterTypes;
    }

    public void setParameterTypes(Class[] parameterTypes) {
        this.parameterTypes = parameterTypes;
    }

    public Object[] getParameters() {
        return parameters;
    }

    public void setParameters(Object[] parameters) {
        this.parameters = parameters;
    }
}
LocalRegister(本地注册)
java 复制代码
package com.yc.register;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author yc
 * @PackageName rpc01
 * @Package com.yc.register
 * @Date 2023/9/6 14:19
 */
public class LocalRegister {

    private static Map<String ,Class> map = new HashMap<>();

    public static void regist(String interfaceName ,String version ,Class implClass){
        map.put(interfaceName+version,implClass);
    }

    public static Class get(String interfaceName ,String version){
        return map.get(interfaceName+version);
    }
}
URL对象
java 复制代码
package com.yc.common;

import java.io.Serializable;

/**
 * @Author yc
 * @PackageName rpc01
 * @Package com.yc.common
 * @Date 2023/9/6 15:11
 */
public class URL implements Serializable {

    private String hostname;
    private Integer port;

    public URL(String hostname, Integer port) {
        this.hostname = hostname;
        this.port = port;
    }

    public String getHostname() {
        return hostname;
    }

    public void setHostname(String hostname) {
        this.hostname = hostname;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }
}
发送http请求
java 复制代码
package com.yc.protocol;

import com.yc.common.Invocation;
import org.apache.commons.io.IOUtils;

import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @Author yc
 * @PackageName rpc01
 * @Package com.yc.protocol
 * @Date 2023/9/6 14:39
 */
public class HttpClient {

    public String send(String hostname, Integer port, Invocation invocation) throws Exception {
        try {
            URL url = new URL("http", hostname, port, "/");
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setDoOutput(true);

            //配置
            OutputStream outputStream = httpURLConnection.getOutputStream();
            ObjectOutputStream oss = new ObjectOutputStream(outputStream);

            oss.writeObject(invocation);
            oss.flush();
            oss.close();

            InputStream inputStream = httpURLConnection.getInputStream();
            String result = IOUtils.toString(inputStream);

            return result;

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
}
ProxyFactory(代理对象)
java 复制代码
package com.yc.proxy;

import com.yc.common.Invocation;
import com.yc.common.URL;
import com.yc.loadbalance.Loadbalance;
import com.yc.protocol.HttpClient;
import com.yc.register.MapRemoteRegister;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author 杨超
 * @PackageName rpc01
 * @Package com.yc.proxy
 * @Date 2023/9/6 15:03
 */
public class ProxyFactory {

    public static <T> T getProxy(Class interfaceClass) {

        Object proxyInstance = Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                String mock = System.getProperty("mock");
//                if (mock != null && mock.startsWith("return:")) {
//                    String result = mock.replace("return:", "");
//                    return result;
//                }


                Invocation invocation = new Invocation(interfaceClass.getName(), method.getName(),
                        method.getParameterTypes(), args);

                HttpClient httpClient = new HttpClient();

                //服务发现
                List<URL> list = MapRemoteRegister.get(interfaceClass.getName());


                //服务调用
                String result = null;
                List<URL> invokedUrls = new ArrayList<>();

                int max = 5;
                while (max > 0) {

                    //负载均衡
                    list.remove(invokedUrls);
                    URL url = Loadbalance.random(list);
                    invokedUrls.add(url);

                    try {
                        result = httpClient.send(url.getHostname(), url.getPort(), invocation);
                        return result;
                    } catch (Exception e) {
                        e.printStackTrace();

                        if (max-- == 0) {
                            continue;
                        }

                        // error-callback = com.yc.helloServiceErrorCallback
                        //容错
                        return "报错了";
                    }

                }
                return result;
            }
        });
        return (T) proxyInstance;
    }

}
MapRemoteRegister (模拟远程注册中心)
java 复制代码
package com.yc.register;

import com.yc.common.URL;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author yc
 * @PackageName rpc01
 * @Package com.yc.register
 * @Date 2023/9/6 15:12
 */
public class MapRemoteRegister {

    private static Map<String, List<URL>> map = new HashMap<>();

    public static void regist(String interfaceName, URL url) {
        List<URL> list = map.get(interfaceName);
        if (list == null) {
            list = new ArrayList<>();
        }
        list.add(url);
        map.put(interfaceName, list);
        saveFile();
    }

    public static List<URL> get(String interfaceName) {
        map = getFile();
        return map.get(interfaceName);
    }

    private static void saveFile() {
        try {
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\yc\\Java\\idea\\idea-work\\project\\rpc01\\temp.txt");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(map);

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

    private static Map<String, List<URL>> getFile() {
        try {
            FileInputStream fileInputStream = new FileInputStream("D:\\yc\\Java\\idea\\idea-work\\project\\rpc01\\temp.txt");
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            return (Map<String, List<URL>>) objectInputStream.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
简单的负载均衡
java 复制代码
package com.yc.loadbalance;

import com.yc.common.URL;

import javax.annotation.Resource;
import java.util.List;
import java.util.Random;

/**
 * @Author 杨超
 * @PackageName rpc01
 * @Package com.yc.loadbalance
 * @Date 2023/9/6 15:19
 */
public class Loadbalance {

    public static URL random(List<URL> urls){
        Random random = new Random();
        int i = random.nextInt(urls.size());
        return urls.get(i);
    }
}
相关推荐
道法自然0402几秒前
Ethernet 系列(8)-- 基础学习::ARP
网络·学习·智能路由器
爱吃生蚝的于勒6 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
苏三有春1 小时前
PyQt5实战——UTF-8编码器功能的实现(六)
开发语言·qt
Vanranrr1 小时前
C++ QT
java·c++·qt
兆。1 小时前
掌握 PyQt5:从零开始的桌面应用开发
开发语言·爬虫·python·qt
cuisidong19972 小时前
5G学习笔记三之物理层、数据链路层、RRC层协议
笔记·学习·5g
南宫理的日知录2 小时前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
数据与后端架构提升之路3 小时前
从神经元到神经网络:深度学习的进化之旅
人工智能·神经网络·学习
一行13 小时前
电脑蓝屏debug学习
学习·电脑
星LZX3 小时前
WireShark入门学习笔记
笔记·学习·wireshark