Dubbo源码解析(十六) Dubbo Transporter

本文深入解析了Dubbo的Transport层,包括Transporter接口及其NettyServer实现。Transporter是Dubbo服务间通信的基础,提供创建Server和Client的功能,默认实现为NettyTransporter。NettyServer涉及属性配置、初始化及通道处理器。通过对NettyServer的分析,揭示了Dubbo如何通过Transporter实现网络通信。
摘要由CSDN通过智能技术生成

Transport 定义

transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec

这里的transport可以理解为一个协议的服务器实现,如tomca是http服务器,这里的就是dubbo协议服务器。

谈起传输层,大家应该都能详细OSI七层模型,那么在计算机网络中,是怎么描述传输层呢?

OSI 模型

In computer networking, the transport layer is a conceptual division of methods in the layered architecture of protocols in the network stack in the Internet protocol suite and the OSI model. The protocols of this layer provide host-to-host communication services for applications.[1] It provides services such as connection-oriented communication, reliability, flow control, and multiplexing.

在这里插入图片描述
图片来自网络,侵删

在计算机网络中,传输层是因特网协议套件和OSI模型中的网络堆栈中的协议的分层体系结构中的方法的概念划分。该层的协议为应用程序提供主机到主机的通信服务。如UDP、TCP。并且提供面向连接的通信,可靠性,流量控制和多路复用等服务。

在dubbo,这个Transporter就是对传输层的实现。它对于提供了dubbo服务间通讯的支持。有了它,各个服务就可以进行网络通信了,不再是信息孤岛了。

Transport

@SPI("netty")
public interface Transporter {

    /**
     * Bind a server.
     */
    @Adaptive({Constants.SERVER_KEY, Constants.TRANSPORTER_KEY})
    Server bind(URL url, ChannelHandler handler) throws RemotingException;

    /**
     * Connect to a server.
     */
    @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})
    Client connect(URL url, ChannelHandler handler) throws RemotingException;

}

通过这个接口定义可以知道:

  1. 通过Transporter可以知道dubbo使用的也是C/S架构
  2. Transport提供了创建服务端和客户端的功能
  3. 默认的Transporter是NettyTransporter
  4. 可以通过server/client、transport来配置server/client的类型,目前支持的类型有netty、mina等

那个Transporter到底是什么呢,下面对使用Netty实现的Transporter进行示例介绍

NettyServer

属性

在这里插入图片描述

首先来瞅瞅,都有什么属性,简要来几个说一说

field desc
handler 通道处理器,用于处理客户端的请求
codec 编解码处理器,用于把客户端的请求和服务端的相应进行编解码,变为Request和Response对象

创建一个NettyServer

可以看到,啥也没做,直接调用的supper方法

public class NettyServer extends AbstractServer implements Server 
 public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
   
        super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)));
    }
}

在这里我们看下这个父类AbstractServer干了什么

public AbstractServer(URL url, ChannelHandler handler) throws RemotingException {
        super(url, handler);
        localAddress = getUrl().toInetSocketAddress();

        String bindIp = getUrl().getParameter(Constants.BIND_IP_KEY, getUrl().getHost());
        int bindPort = getUrl().getParameter(Constants.BIND_PORT_KEY, getUrl().getPort());
        if (url.getParameter(Constants.ANYHOST_KEY, false) || NetUtils.isInvalidLocalHost(bindIp)) {
            bindIp = Constants.ANYHOST_VALUE;
        }
        bindAddress = new InetSocketAddress(bindIp, bindPort);
        // 允许接收的最大请求数
        this.accepts = url.getParameter(Constants.ACCEPTS_KEY, Constants.DEFAULT_ACCEPTS);
        
        this.idleTimeout = url.getParameter(Constants.IDLE_TIMEOUT_KEY, Constants.DEFAULT_IDLE_TIMEOUT);
        try {
            // 实际启动服务方法,模板方法,交由子类实现
            doOpen();
            if (logger.isInfoEnabled()) {
                logger.info("Start " + getClass().getSimpleName() + " bind " + getBindAddress() + ", export " + getLocalAddress());
            }
        } catch (Throwable t) {
            throw new RemotingException(url.toInetSocketAddress(), null, "Failed to bind " + getClass().getSimpleName()
                    + " on " + getLocalAddress() + ", cause: " + t.getMessage(), t);
        }
        //fixme replace this with better method
        DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
        executor = (ExecutorService) dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY, Integer.toString(url.getPort()));
    }

上面初始化了服务器、本地地址以及服务器对外暴露地址、允许接收的最大请求accepts、空闲时间等

public AbstractEndpoint(URL url, ChannelHandler handler) {
        super(url, handler);
        // 根据url获得
        this.codec = getChannelCodec(url);
        this.timeout = url.getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
        this.connectTimeout = url.getPositiveParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT);
    }
    
    

总的来说初始化了,编解码类Codec、通讯超时时间timeout、建立连接超时时间connect.timeout

 public AbstractPeer(URL url, ChannelHandler handler) {
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }
        if (handler == null) {
            throw new IllegalArgumentException("handler == null");
        }
        this.url = url;
        this.handler = handler;
    }

以上就是启动一个Netty服务器之前的准备工作。但是刚才可能注意到在AbstractServer中有一个doOpen方法,下面一起瞅瞅怎么启动一个服务器的?

启动服务器

 protected void doOpen() throws Throwable {
   
        bootstrap = new ServerBootstrap();

        bossGroup =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值