深度解析dubbo网络传输层Transporter

本文基于dubbo v2.6.x

1.传输层

dubbo网络传输层的一个介绍(dubbo 官方文档:链接):

抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec

2. Transporter

Transporter是一个接口,抽象了客户端连接connect与服务端的端口绑定bind方法。
在这里插入图片描述
Transporter是dubbo spi一个扩展点,默认实现类为netty,这里这个netty 是netty4,bind与connect 方法实现会根据@Adaptive上面的server,client ,transporter属性来自适应选择合适的实现类。
在这里插入图片描述
我们看到它的实现类 有netty3 ,netty4 ,mina,grizzly(这个也是一个基于java nio 高性能网络基础框架),mock 实现。后面我们将解析其实现。

你可以使用client 或者server 属性配置你的网络传输层使用哪个框架实现,比如:

<dubbo:protocol accesslog="true" name="dubbo" port="18109"  client="mina" server="mina"/>

也可以某个引用使用哪个client

<dubbo:reference interface="com.xuzhaocai.dubbo.provider.IUserInfoService"  client="mina">
@Reference(check = false,client = "netty")

3.Transporters

Transporters是网络传输层的门面类,它统一了网络传输层的访问入口,提供了一堆bind 与 connect静态方法,与信息交换层的Exchangers功能一致。
在这里插入图片描述
我们先来看下它的bind方法:

  public static Server bind(URL url, ChannelHandler... handlers) throws RemotingException {
        //验证
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }
        if (handlers == null || handlers.length == 0) {
            throw new IllegalArgumentException("handlers == null");
        }
        ChannelHandler handler;
        if (handlers.length == 1) {
            handler = handlers[0];
        } else {   // 多个channal  对 Channel分发   ChannelHandlerDispatcher 循环
            handler = new ChannelHandlerDispatcher(handlers);
        }
        // 真正服务器 进行bind
        return getTransporter().bind(url, handler);
    }

首先是检验url与handler,如果是多个handler的话就是用ChannelHandlerDispatcher 这个handler分发器(这个handler就是做某件事的时候就会循环那一堆handler做某件事)封装。最后调用getTransporter 获得具体Transporter 实现,然后调用bind方法。

public static Transporter getTransporter() {  // 获取transporter
        return ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension();
}

可以看到getTransporter 就是使用dubbo spi技术自适应获得Transporter 的具体实现。
接下来看下connect连接方法的实现:

public static Client connect(URL url, ChannelHandler... handlers) throws RemotingException {
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }
        ChannelHandler handler;
        if (handlers == null || handlers.length == 0) {
            handler = new ChannelHandlerAdapter();// handler 是null的情况
        } else if (handlers.length == 1) {
            handler = handlers[0];//一个handler的情况
        } else {///多个的情况
            handler = new ChannelHandlerDispatcher(handlers);
        }
        return getTransporter().connect(url, handler);
}

在connect方法中可以看到检查url,它是允许handler为空的,如果空的话就创建一个ChannelHandlerAdapter(这里面其实就是一堆空方法,这种就是发出去 不准备接收响应那种),如果是多个handler的话也是使用ChannelHandlerDispatcher 包装下,最后是getTransporter获得具体Transporter然后进行connect连接。

4. NettyTransporter

NettyTransporter 在上面的UML类图中可以看到是有两个,其实他们两个分别在两个子项目中,一个是netty3版本的实现,一个是netty4版本的实现。
我们就来看下netty4实现的吧

/**
 * 实现 Transporter 接口,基于 Netty4 的网络传输实现类
 */
public class NettyTransporter implements Transporter {
    /**
     * 扩展名
     */
    public static final String NAME = "netty";
    @Override
    public Server bind(URL url, ChannelHandler listener) throws RemotingException {
        return new NettyServer(url, listener);
    }
    @Override
    public Client connect(URL url, ChannelHandler listener) throws RemotingException {
        return new NettyClient(url, listener);
    }
}

可以看到bind方法实现是创建了一个netty服务端对象返回的,connect方法中创建了一个netty 客户端对象返回的, 其实netty3 ,mina, Grizzly 的Transporter实现 代码也是这个样子的,都是创建对应的客户端对象,创建对应的服务端对象。
netty3(虽然NettyServer ,NettyClient 与netty4实现类名一样,但是不是同一个类。):
在这里插入图片描述
mina:
在这里插入图片描述
Grizzly:
在这里插入图片描述

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页