1. 程式人生 > >dubbo原始碼深度解讀四之remoting模組

dubbo原始碼深度解讀四之remoting模組

前言:remoting模組是遠端通訊模組,相當於Dubbo協議的實現,是一個為Dubbo專案處理底層網路通訊的層。具體結合了netty,mina等進行實現。

一,dubbo-remoting-api
首先結合文件的圖先了解一下基礎介面包的主要類。
這裡寫圖片描述
1,ChannelHandler是抽象的通道事件處理器,同時注意到它的註解也是SPI

@SPI
public interface ChannelHandler {

    void connected(Channel channel) throws RemotingException;

    void disconnected(Channel channel) throws
RemotingException; void sent(Channel channel, Object message) throws RemotingException; void received(Channel channel, Object message) throws RemotingException; void caught(Channel channel, Throwable exception) throws RemotingException; }

2,Codec2.介面定義了編碼解碼規範,與廢棄的介面Codec相比,Codec2沒有依賴jdk的輸入輸出流, 以dubbo的ChannelBuffer為核心便於更好的整合(關於各個Codec2的實現類例如DubboCodec,會和rpc模組一起深入解讀)

@SPI
public interface Codec2 {

    @Adaptive({Constants.CODEC_KEY})
    void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException;

    @Adaptive({Constants.CODEC_KEY})
    Object decode(Channel channel, ChannelBuffer buffer) throws IOException;


    enum DecodeResult {
        NEED_MORE_INPUT, SKIP_SOME_INPUT
    }

}

3,Transporter
bind 根據URL和ChannelHandler 生成Server, connect 根據URL和ChannelHandler

@SPI("netty")
public interface Transporter {

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

    @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})
    Client connect(URL url, ChannelHandler handler) throws RemotingException;

}

4,Endpoint。Client和Server都繼承的一個介面類

5,Dispatcher。定義channelHandler對Channel的操作(哪些走執行緒池)

@SPI(AllDispatcher.NAME)  
public interface Dispatcher {  

    @Adaptive({Constants.DISPATCHER_KEY, "dispather", "channel.handler"}) // 後兩個引數為相容舊配置  
    ChannelHandler dispatch(ChannelHandler handler, URL url);  

}  

二,服務端整合netty
1,先看下NettyServer的類圖
這裡寫圖片描述

2,處理流程
這裡寫圖片描述
其中Netty區域的類,都是擴充套件了了Netty自帶類。
1.1 InternalDecoder:負責TCP層協議的解析,處理TCP粘包。(當然這個解析也包含序列化的處理)。
1.2 InternalEncoder: 協議封裝。
1.3 NettyHandler:客戶通道共享的處理器(請參閱Netty的通道處理器模型),轉換Netty的通道事件到Dubbo事件。
1.4 NettyServer:處理連線數量。
1.5 MultiMessageHandler:多訊息處理。
1.6 HeartbeatHandler:心跳訊息。
1.7 AllChannelHandler:委派業務請求到執行緒池。

3,NettyHandler的實現
繼承org.jboss.netty.channel.SimpleChannelHandler,來處理org.jboss.netty.channel.Channel的連線讀寫事件。此時NettyHandler就可以委託dubbo的com.alibaba.dubbo.remoting.ChannelHandler介面實現來完成具體的功能,在交給com.alibaba.dubbo.remoting.ChannelHandler介面實現之前,需要先將netty自己的org.jboss.netty.channel.Channel channel轉化成上述的NettyChannel。
其實就是相當於轉換Netty的通道事件到Dubbo事件
摘取部分程式碼來看一下就知道了

@Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler);
        try {
            if (channel != null) {
                channels.put(NetUtils.toAddressString((InetSocketAddress) ctx.getChannel().getRemoteAddress()), channel);
            }
            //轉換到ChannelHandler的connected
            handler.connected(channel);
        } finally {
            NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
        }
    }

4,NettyServer啟動流程
這裡寫圖片描述
按照netty自己的API啟動方式,然後依據外界傳遞進來的com.alibaba.dubbo.remoting.ChannelHandler介面實現,創建出NettyHandler,最終對使用者的連線請求的處理全部交給NettyHandler來處理,NettyHandler又交給了外界傳遞進來的com.alibaba.dubbo.remoting.ChannelHandler介面實現。
至此就將所有底層不同的通訊實現全部轉化到了外界傳遞進來的com.alibaba.dubbo.remoting.ChannelHandler介面的實現上了。

而上述Server介面的另一個分支實現HeaderExchangeServer則充當一個裝飾器的角色,為所有的Server實現增添了如下功能:
向該Server所有的Channel依次進行心跳檢測:

  • 如果當前時間減去最後的讀取時間大於heartbeat時間或者當前時間減去最後的寫時間大於heartbeat時間,則向該Channel傳送一次心跳檢測
  • 如果當前時間減去最後的讀取時間大於heartbeatTimeout,則伺服器端要關閉該Channel,如果是客戶端的話則進行重新連線(客戶端也會使用這個心跳檢測任務)

三,客戶端整合Netty
伺服器端了解了之後,客戶端就也非常清楚了,整體類圖如下:
這裡寫圖片描述
NettyClient在使用netty的API開啟客戶端之後,仍然使用NettyHandler來處理。還是最終轉化成com.alibaba.dubbo.remoting.ChannelHandler介面實現上了。
我們可以看到這樣整合完成之後,就完全遮蔽了底層通訊細節,將邏輯全部交給了com.alibaba.dubbo.remoting.ChannelHandler介面的實現上了。從上面我們也可以看到,該介面實現也會經過層層裝飾類的包裝,才會最終交給底層通訊。