dubbo模拟框架的自我搭建一

dubbo模拟框架的自我搭建一

rpc:远程方法调用
框架实现思路:
1.提供一个服务得接口
2.提供服务得实现类
3.将服务注册到注册中心,将服务注册到本地
4.使用tomcat处理请求

整体流程图:
在这里插入图片描述
说明:
1.服务消费者向远程注册中心获取服务提供者的url
2.通过url连接服务提供者
3.服务提供者通过服务消费者提供的参数(包括执行参数,执行方法,接口名等)去本地注册中找实现方法执行,并返回执行结果

限制与优化:
限制:因为本项目没有连接第三方,如redis,zk。所以采用了对象刷磁盘来达到数据同步
优化:服务消费者向远程注册中心获取服务提供者的url时可以使用代理模式来代理每次需要传递的执行方法,执行参数等。

项目接口预览:
在这里插入图片描述

一:引入依赖

  <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-http</artifactId>
            <version>4.5.11</version>
        </dependency>

二.编写服务提供者Provider

public class Provider {
    public static void main(String[] args) {
        // 1.提供服务接口
        // 2.提供实现类
        // 3.注册服务(注册中心注册,本地注册)

        //注册中心注册
        URL url = new URL("127.0.0.1", 8081);
        RemoteMapRegister.regist(HelloService.class.getName(),url);

        //本地注册  接口名字:实现类
        LocalMapRegister.regist(HelloService.class.getName(), HelloServiceImpl.class);

        // 4.暴露服务(启动tomcat ,nettyServer,接收处理请求)
        //启动tomcat
        HttpServer httpServer = new HttpServer();
        httpServer.start(url.getHostName(), url.getPort());
    }
}

1.url

public class URL implements Serializable {
    private String hostName;
    private Integer port;

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

    public void setHostName(String hostName) {
        this.hostName = hostName;
    }

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

    public String getHostName() {
        return hostName;
    }

    public Integer getPort() {
        return port;
    }
}

2.服务中心注册 RemoteMapRegister.的regist,get

/**
 * readFile,saveFile 是为了保证资源在两个jvm中能读到,实际开发可以用redis,zk
 */
public class RemoteMapRegister {
    private static Map<String, List<URL>> REGISTER=new HashMap<>();


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

    public static  List<URL> get(String interfance){
        if(REGISTER.size()==0){
            REGISTER=readFile();
        }
        return REGISTER.get(interfance);
    }
    private static  void saveFile(){
        try {
            FileOutputStream fileOutputStream = new FileOutputStream("/temp.text");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(REGISTER);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static Map<String,List<URL>> readFile(){
        try {
            FileInputStream fileInputStream = new FileInputStream("/temp.text");
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
          return (Map<String, List<URL>>) objectInputStream.readObject();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

3.本地注册 LocalMapRegister.regist

public class LocalMapRegister {
    private static Map<String, Class> LOCAL_REGISTER=new HashMap<>();


    public static  void  regist(String interfance, Class implClass) {

        LOCAL_REGISTER.put(interfance,implClass);
    }

    public static  Class get(String interfance){
        return LOCAL_REGISTER.get(interfance);
    }

4.httpServer.start启动tomcat,接收处理请求

public class HttpServer {
    public  void start(String hostName,Integer port){
        Tomcat tomcat = new Tomcat();
        Server server = tomcat.getServer();
        Service service = server.findService("Tomcat");

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

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

        Host host=new StandardHost();
        host.setName(hostName);
    String contextPath="";
    Context 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 DispathcherServlet());
    context.addServletMappingDecoded("/*","dispatcher");

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

}
5.DispathcherServlet分发请求处理

public class DispathcherServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        new HeepServlerHandler().handler(req,resp);

    }
}
public class HeepServlerHandler {
    public  void handler(HttpServletRequest req, HttpServletResponse resp){
        try {
            Invocation invocation = JSONObject.parseObject(req.getInputStream(), Invocation.class);

            String interfaceName = invocation.getInterfaceName();
            Class implClass = LocalMapRegister.get(interfaceName);
            Method method = implClass.getMethod(invocation.getMethodName(), invocation.getParamType());
            String result = (String) method.invoke(implClass.newInstance(), invocation.getParams());
            IOUtils.write(result,resp.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    
}

三:编写服务消费者Consumer

public class Consumer {
    public static void main(String[] args) {


        HelloService helloService = ProxyFactory.getProxy(HelloService.class);
        String result = helloService.sayHello("123456");
        System.out.println(result);
    }
}

创建代理工厂ProxyFactory

public class ProxyFactory {
    public static <T> T getProxy(final Class interfaceClass){
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                HttpClient httpClient = new HttpClient();
                Invocation invocation = new Invocation(interfaceClass.getName(),method.getName(),method.getParameterTypes(),args);

                List<URL>  urls =RemoteMapRegister.get(interfaceClass.getName());
                //负载均衡,拿一个可用得
                Integer index=  RandomUtil.randomInt(urls.size());
                URL url =urls.get(index);
                String result = httpClient.post(url.getHostName(), url.getPort(), invocation);
               return result;
            }
        });
    }
}

发送请求

public class HttpClient {
    public String  post(String hostName, Integer port, Invocation invocation){
        try {
            URL url = new URL("http", hostName, port, "/");
            String post = HttpUtil.post(url.toString(), JSONObject.toJSONString(invocation));
            return post;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;

    }

}

测试:启动服务提供者provider ,消费者consumer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值