dubbo源码实践-protocol层例子

Posted alf_cee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo源码实践-protocol层例子相关的知识,希望对你有一定的参考价值。

1 概述

本文提供了基于protocol层的一个客户端、服务端代码例子。

从dubbo 2.7的架构图上可以看到protocol层上在Remoting层之上的,个人理解Protocol层不在讨论客户端和服务端的概念了,开始讨论服务提供者和服务消费者的概念了。

参考上一篇dubbo源码实践-protocol层-invoker理解,本文理解起来应该不难。

2 例子

2.1 项目截图

ProtocolClientTest服务消费者(即客户端)、ProtocolServerTest服务提供者(即提供者)。业务服务IAlfService是接口、AlfService是实现类。

2.2 服务提供者

ProtocolServerTest代码

package org.example.dubbo.protocol;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ServiceRepository;
import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
import org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory;
import org.example.test.protocol.AlfService;
import org.example.test.protocol.IAlfService;

import java.io.IOException;

/** 服务端代码, 2022/12/29. */
public class ProtocolServerTest 
    public static void main(String[] args) throws IOException 
        //Protocol 层的SPI
        Protocol dubboProtocol = new DubboProtocol();
        //业务服务
        AlfService alfService = new AlfService();
        //代理工厂
        ProxyFactory jdkProxyFactory = new JdkProxyFactory();
        //创建URL
        URLBuilder urlBuilder = new URLBuilder();
        urlBuilder.setHost("localhost");
        urlBuilder.setPort(9999);
        //指定调用的服务
        urlBuilder.setPath("alf/haha");
//        urlBuilder.addParameter("version", "1.0");
//        urlBuilder.addParameter("group", "abc");
        URL url = urlBuilder.build();
        //获取本地Invoker, 该Invoker内部包装了alfService。
        Invoker<IAlfService> invoker = jdkProxyFactory.getInvoker(alfService, IAlfService.class, url);
        //暴露服务, 最后会在端口9999上启动dubbo服务端程序
        Exporter<IAlfService> export = dubboProtocol.export(invoker);
        //注册服务, 否则请求到服务端找不到IAlfService的实现
        ServiceRepository repository = ApplicationModel.getServiceRepository();
        repository.registerService("alf/haha", IAlfService.class);

        System.in.read();

    

2.3 服务消费者

ProtocolClientTest代码

package org.example.dubbo.protocol;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
import org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory;
import org.example.test.protocol.IAlfService;

import java.io.IOException;

/** 客户端代码, 2022/12/29. */
public class ProtocolClientTest 
    public static void main(String[] args) throws IOException 
        //Protocol 层的SPI
        Protocol protocol = new DubboProtocol();
        //代理层, 用来创建代理对象。客户端需要通过ProxyFactory获取远程Invoker的代理类
        ProxyFactory proxyFactory = new JdkProxyFactory();
        //创建URL
        URLBuilder urlBuilder = new URLBuilder();
        urlBuilder.setHost("localhost");
        urlBuilder.setPort(9999);
        //服务的名字
        urlBuilder.setPath("alf/haha");
        //配置客户端离开发送请求数据
        urlBuilder.addParameter("sent", true);
//        urlBuilder.addParameter("version", "1.0");
//        urlBuilder.addParameter("group", "abc");
        URL url = urlBuilder.build();
        //创建远程调用的Invoker
        Invoker<IAlfService> invoker = protocol.refer(IAlfService.class, url);
        //创建IAlfService的代理类
        IAlfService alfService = proxyFactory.getProxy(invoker);

        String s = alfService.sayHolle("111");
        System.out.println("返回结果: " + s);

        System.in.read();

    

2.4 业务服务类

IAlfService接口

package org.example.test.protocol;

/** 业务服务类接口 */
public interface IAlfService 
    String sayHolle(String hi);

AlfService类

package org.example.test.protocol;

/** 业务类 */
public class AlfService implements IAlfService
    @Override
    public String sayHolle(String hi) 
        System.out.println("AlfService call");
        return "hi " + hi;
    

2.5 代码运行结果

1)先启动ProtocolServerTest类。可以看到启动和暴露服务成功。

2)启动ProtocolClientTest类。消费者调用alfService.sayHolle("111"),接收到返回是"hi 111"。

3 总结

细心的读者已经发现代码中还使用Proxy层的类,Protocal层+Proxy层已经实现了服务的发布与消费。

官方对Protocal层和Proxy层的解释:

在 RPC 中,Protocol 是核心层,也就是只要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 调用,然后在 Invoker 的主过程上 Filter 拦截点。

Proxy 层封装了所有接口的透明化代理,而在其它层都以 Invoker 为中心,只有到了暴露给用户使用时,才用 Proxy 将 Invoker 转成接口,或将接口实现转成 Invoker,也就是去掉 Proxy 层 RPC 是可以 Run 的,只是不那么透明,不那么看起来像调本地服务一样调远程服务。

这里的透明指的应该是服务消费者IAlfService alfService = proxyFactory.getProxy(invoker);, 我们直接调用IAlfService接口发送请求,而不是调用invoker来发送请求。

4 遗留问题

服务端提供服务时,不加下面两条语句,请求到达服务端后是找不到对应的业务service(即AlfService)的实例的。含义还需要理解一下。

ServiceRepository repository = ApplicationModel.getServiceRepository();
        repository.registerService("alf/haha", IAlfService.class);

以上是关于dubbo源码实践-protocol层例子的主要内容,如果未能解决你的问题,请参考以下文章

dubbo源码实践-protocol层-invoker理解

dubbo源码实践-protocol层-invoker理解

dubbo源码实践-config层例子

dubbo源码实践-config层例子

dubbo源码实践-Exchange 信息交换层例子

dubbo源码实践-Exchange 信息交换层例子