spark-network-common模塊底層使用netty作爲通訊框架,可以實現rpc消息、數據塊和數據流的傳輸。
Message類圖:
所有request消息都是RequestMessage的子類
所有response消息都是ResponseMessage的子類
TransportClient主要提供了三個方法:
//通過給定的streamId,獲取遠端數據流
public void stream(final String streamId, final StreamCallback callback);
//發送一份不透明的消息到遠端
public long sendRpc(ByteBuffer message, final RpcResponseCallback callback);
//通過給定的streamId,獲取遠端的數據塊
public void fetchChunk(long streamId,final int chunkIndex,final ChunkReceivedCallback callback);
Channel Pipeline:
通過TransportClientFactory的createClient方法追蹤ChannelInitializer設置,最後在TransportContext的initializePipeline方法中可以看到具體的Handler的配置:
channel.pipeline()
.addLast("encoder", encoder)
.addLast(TransportFrameDecoder.HANDLER_NAME, NettyUtils.createFrameDecoder())
.addLast("decoder", decoder)
.addLast("idleStateHandler", new IdleStateHandler(0, 0, conf.connectionTimeoutMs() / 1000))
.addLast("handler", channelHandler);
此處得到的handler鏈爲:
MessageEncoder-->TransportFrameDecoder-->MessageDecoder-->IdleStateHandler-->TransportChannelHandler
MessageEncoder:負責將消息轉換爲netty框架中的ByteBuf
MessageDecoder:負責網絡傳輸的的ByteBuf轉換爲具體的消息
TransportFrameDecoder:負責接收網絡傳輸的ByteBuf,解析爲一個指定大小的ByteBuf交予MessageDecoder,或者交給StreamInterceptor處理
IdleStateHandler:心跳檢測
TransportChannelHandler:負責消息的具體處理
發送端發送消息的流程:
- 通過TransportClient的實例發送RequestMessage消息
MessageEncoder把消息轉換爲ByteBuf
所有RequestMessage的子類都繼承了AbstractMessage,而AbstractMessage有一個叫body的filed,該字段在RpcRequest中被用來存儲具體的請求內容(不止RpcRequest)。當body爲空時該消息直接轉換爲ByteBuf;不爲null時,MessageEncoder將消息轉換爲MessageWithHeader,MessageWithHeader繼承了AbstractReferenceCounted ,實現了FileRegion ,最後消息仍會轉換爲ByteBuf。注意:MessageWithHeader提供了發送文件的能力。MessageWithHeader類:
class MessageWithHeader extends AbstractReferenceCounted implements FileRegion- ByteBuf被髮送到網絡(ByteBuf中包含這個消息的總長度、字段長度、具體內容等信息)
接收端接收消息並響應:
- TransportFrameDecoder負責拼接一個RequestMessage所需的完整ByteBuf
- MessageDecoder將消息解析爲一個RequestMessage消息
- TransportChannelHandler將消息交給TransportRequestHandler具體處理
- TransportRequestHandler將ResponseMessage消息傳遞給MessageEncoder
- MessageEncoder把消息轉換爲ByteBuf(同上)
發送端接收響應消息:
- TransportFrameDecoder負責拼接一個消息所需的完整ByteBuf,如果是StreamResponse消息並且body是一個FileRegion,那麼先拼接這個消息的ByteBuf(注意:StreamResponse消息最終傳輸到網絡上時本身不包含FileRegion的ByteBuf)
- MessageDecoder將消息解析爲一個ResponseMessage消息
- TransportChannelHandler將消息交給TransportResponseHandler具體處理
- 如果StreamResponse是一個包含FileRegion的消息,TransportResponseHandler在Channel Pipeline中添加一個handler:StreamInterceptor。TransportFrameDecoder將使用StreamInterceptor處理後續的FileRegion的ByteBuf。