rpc学习笔记

3 篇文章 0 订阅

rpc

rpc 框架dubbo在使用时可以让使用者调用远程的接口的时候犹如调的本地接口,然而一个远程过程调用一定是会使用网络和序列化的,因此抽象一点,dubbo提供的核心的能力就是通过动态代理的方式把接口的网络操作和序列化操作代理掉,对于使用者变成是透明的。dubbo在这个核心能力之上,外加了一些过滤,轮询,服务注册发现等功能,同时对网络的操作和序列化的操作通过spi机制加入了很多动态的扩展,使得dubbo越来越庞大。因此理解dubbo,最好是从他核心去看,抽象出他的本质是要干什么再来看就会清楚一些。

基于java实现简单的rpc

上面说了,dubbo抽象出核心的能力就是通过动态代理的方式把接口的网络操作和序列化操作代理掉。之所以他很复杂,是因为在这个核心之上加入了其他辅助功能。那么通过一个动态代理就可以实现简单的rpc

提供查询当前时间服务的接口

package api;

/**
 * @Author: Jimmy
 * @Date: 2019-10-30 18:06
 */
public interface TimeService {

    public long getCurrentTimeMillis() throws Throwable;

    public Long getCurrentTimeSec() throws Throwable;

}

服务端timeService的具体实现

package provide;

import api.TimeService;

/**
 * @Author: Jimmy
 * @Date: 2019-10-30 18:08
 */
public class TimeServiceImpl implements TimeService {

    public long getCurrentTimeMillis()  {
        return System.currentTimeMillis();
    }

    public Long getCurrentTimeSec()  {
        return System.currentTimeMillis()/1000;
    }
}

服务端通过代理暴露服务(为了简单,这是用静态代理,事实是使用动态代理让使用者不知道这一层的代码)

package provide;

import api.TimeService;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @Author: Jimmy
 * @Date: 2019-10-30 18:10
 */
public class TimeServiceProvideProxy extends Thread {

    //被代理的对象(具体的业务处理实现类)
    private TimeService timeService;

    public TimeServiceProvideProxy(TimeService timeService) {
        // 传入代理对象(具体的业务处理实现类)
        this.timeService = timeService;
    }

    @Override
    public void run() {
        try {
            // 打开服务端Socket
            ServerSocket serverSocket = new ServerSocket(9000);
            // 接受客户端的请求
            Socket socket = serverSocket.accept();
            while (socket != null) {
                //   ObjectInputStream是java 提供的序列化/反序列化的一种工具
                ObjectInputStream inStream =
                        new ObjectInputStream(socket.getInputStream());
                String method = (String) inStream.readObject();
                //根据客户端传入的请求 找到具体的方法,使用实现类去执行
                if (method.equals("getCurrentTimeMillis")) {
                    long currentTimeMillis = timeService.getCurrentTimeMillis();
                    ObjectOutputStream outStream =
                            new ObjectOutputStream(socket.getOutputStream());
                    // return result
                    outStream.writeLong(currentTimeMillis);
                    outStream.flush();
                }
                if (method.equals("getCurrentTimeSec")) {
                    long currentTimeSec = timeService.getCurrentTimeSec();
                    ObjectOutputStream outStream =
                            new ObjectOutputStream(socket.getOutputStream());
                    // 返回结果 通过  ObjectOutputStream序列化
                    outStream.writeLong(currentTimeSec);
                    outStream.flush();
                }
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

客户端发起请求的代理(为了简单,这是用静态代理,事实是使用动态代理让使用者不知道这一层的代码)

package consumer;

import api.TimeService;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

/**
 * @Author: Jimmy
 * @Date: 2019-10-30 18:14
 */
public class TimeServiceClientProxy implements TimeService {

    private Socket socket;

    public TimeServiceClientProxy() throws Throwable{
        // 客户端的网络链接
        socket = new Socket("127.0.0.1", 9000);
    }

    public long getCurrentTimeMillis() throws Throwable {
        // 没有具体的业务,仅仅是封装一个请求及协议(这里的请求很简单就是 一个方法名)
        // 服务端拿到这个请求 通过反序列化拿到结果,协议是定义好的就是一个简单的方法名,服务端直接根据方法名去执行具体的方法
        ObjectOutputStream outStream =
                new ObjectOutputStream(socket.getOutputStream());
        outStream.writeObject("getCurrentTimeMillis");
        outStream.flush();
        ObjectInputStream inStream =
                new ObjectInputStream(socket.getInputStream());
        return inStream.readLong();
    }

    public Long getCurrentTimeSec() throws Throwable {
        ObjectOutputStream outStream =
                new ObjectOutputStream(socket.getOutputStream());
        outStream.writeObject("getCurrentTimeSec");
        outStream.flush();
        ObjectInputStream inStream =
                new ObjectInputStream(socket.getInputStream());
        return inStream.readLong();
    }

这样一个最简单的rpc调用就写好了,客户端是没有具体的实现的,具体的实现在服务端。客户端通过和服务端一起定义好的协议(方法名)通过一样的序列化方式。完成远程调用

启动服务端

import provide.TimeServiceImpl;
import provide.TimeServiceProvideProxy;

/**
 * @Author: Jimmy
 * @Date: 2019-10-30 18:18
 */
public class ProvideMain {

    public static void main(String[] args) {
        TimeServiceImpl timeServiceImpl = new TimeServiceImpl();
        TimeServiceProvideProxy timeServiceProvideProxy = new TimeServiceProvideProxy(timeServiceImpl);
        timeServiceProvideProxy.start();
        System.out.println("服务端已经启动。。。。。。");
    }
}

启动客户端

import consumer.TimeServiceClientProxy;

/**
 * @Author: Jimmy
 * @Date: 2019-10-30 18:20
 */
public class ConsumerMain {

    public static void main(String[] args) {
        try {
            TimeServiceClientProxy timeServiceClientProxy = new TimeServiceClientProxy();

            long millis = timeServiceClientProxy.getCurrentTimeMillis();
            System.out.println("millis:"+millis);
            Long sec = timeServiceClientProxy.getCurrentTimeSec();
            System.out.println("sec:"+sec);

        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值