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);
    }
}
相关推荐
blasit4 小时前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
范特西.i5 天前
QT聊天项目(8)
开发语言·qt
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习