【Java】Dubbo底层RPC模拟实现

模拟Dubbo底层RPC实现,Socket通信,实现参数回调功能。


之前也写过自己的RPC框架,就想着去了解一下Dubbo底层核心的RPC并模拟实现一下。发现Dubbo底层的RPC相比我之前更加完善,特别是【参数回调】这个我之前并没有的功能:

RPC为远程方法调用

故,我们要实现的是消费者远程调用服务器的方法。

整体思路:消费者发送要实现的方法信息及参数,服务器反射执行后再发送回消费者。


目录

1.注册中心

2.服务提供者

2.1 上下文中心

2.2 RPC服务端

2.3 代理工厂

3.测试

3.1 服务暴露者

3.2 服务接口

3.3 服务接口实现类

3.4 订单实体类

3.5 消费者示例

3.6 运行结果


1.注册中心

先看注册中心,其作用是保存与他连接的服务暴露者并存储服务暴露者信息。通过长连接连接服务暴露者,如果服务暴露者异常中断,注册中心则会从服务列表中移除该服务。本项目中使用zookeeper


2.服务提供者

先从服务提供者来看,服务提供者先向注册中心注册,需要发送给注册中心他的服务名服务地址(ip:port),方便消费者从注册中心获得服务,连接,调用。

此外,为了让消费者通过接口调用服务暴露者方法,服务暴露者本身需要存储 <接口, 接口实现类模板> hashMap,当消费者通过接口远程调用方法时,匹配到实现类,并反射执行。

2.1 上下文中心

上下文中心的作用是保存隐式参数

何为隐式参数?举个例子来说就是消费者远程调用服务暴露者方法,想要额外传递的参数。这个参数不是该方法所需的参数。

这里用到了ThreadLocal:即,每个线程拥有它自己的LOCAL和SERVER,说白了就是各自的一个map,以键值对的方式存放该线程服务器和消费者的隐式参数。键:参数名  值:参数

/**
 * 隐式上下文参数对象
 */
public class FYContext {

    /**
     * 客户端本地上下文
     */
    private static ThreadLocal<FYContext> LOCAL = new ThreadLocal<FYContext>();

    /**
     * 服务端上下文
     */
    private static ThreadLocal<FYContext> SERVER = new ThreadLocal<FYContext>();

    /**
     * 隐式参数容器
     */
    private final Map<String, String> attachment = new HashMap<String, String>();

    /**
     * 获得本地上下文对象
     * @return
     */
    public static FYContext getContext() {
        FYContext fyContext = LOCAL.get();
        if (fyContext == null) {
            fyContext = new FYContext();
            LOCAL.set(fyContext);
        }
        return fyContext;
    }

    /**
     * 获得服务端上下文对象
     * @return
     */
    public static FYContext getServerContext() {
        FYContext fyContext = SERVER.get();
        if (fyContext == null) {
            fyContext = new FYContext();
            SERVER.set(fyContext);
        }
        return fyContext;
    }

    /**
     * 清楚客户端上下文
     */
    public void removeContext() {
        LOCAL.remove();
    }

    /**
     * 清除服务器上下文
     */
    public void removeServerContext() {
        SERVER.remove();
    }

    /**
     * 存储需要传递的参数
     * @param key 参数键
     * @param value 参数值
     */
    public void setAttachment(String key, String value) {
        attachment.put(key, value);
    }

    /**
     * @return 本地线程所有的隐方参数容器
     */
    public Map<String, String> getAttachments() {
        return attachment;
    }

    /**
     * 获得容器参数值
     * @param key
     * @return
     */
    public String getAttachment(String key) {
        return attachment.get(key);
    }

    /**
     * 接收所有的参数
     * @param attachment 参数容器
     */
    public void setAttachments(Map<String, String> attachment) {
        this.attachment.putAll(attachment);
    }
}

2.2 RPC服务端

rpc服务端就是服务暴露者,说说其需要实现的功能及实现逻辑。

1.向注册机注册服务

2.自身注册接口,创建SocketServer。

3.当有socket连接与之通信,接收需要的接口名,方法名,参数类型,参数值,隐士参数,反射执行,发送回消费者。(这是没有参数回调的情况)

4.当消费者传递来的参数是需要回调的,服务暴露者还需去和消费者“交流”,远程调用消费者的方法来“完善”参数,这里可能有点绕,一会下面有例子来说明。

下面为服务端代码:

/**
 * RPC服务端
 */
public class Server {

    /**
     * zookeeper 服务注册根节点
     */
    public static final String ZOOKEEPER_NOOD_FY = "/FY";

    /**
     * 服务本地注册容器
     */
    private Map<String, Class> serverReigster = new HashMap<String, Class>();

    /**
     * 服务请求接收端
     */
    private ServerSocket serverSocket;

    /**
     * 多线程容器
     */
    private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    /**
     * 结果标记
     */
    public final static int FLAG_RESULT = 0;

    /**
     * 远程回调标记
     */
    public final static int FLAG_INVOKER = 1;

    /**
     * zk服务地址
     */
    public final static String ZOOKEEPER_ADDRESS = "localhost";

    /**
     * zk服务端口
     */
    public final static int port = 2181;

    /**
     * zk会话超时时间
     */
    public final static int TIMEOUT = 1000 * 3;

    /**
     * 服务提供者地址
     */
    public final static int SERVER_PORT = 10086;

    /**
     * 开启服务
     * @param ip 暴漏地址
     * @param port 暴露端口
     */
    publ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值