談談你對Netty中,Pipeline工作原理的理解?
1位工作8年的小伙伴,去某東面試IM部門,被問到這樣一道面試題。說,請你談一談你對Netty Pipeline設計原理的理解。當時,他說只是用過Netty的Pipline,原理沒有深入了解過,然后就沒有然后了。
今天,我給大家講一講,我對Netty Pipeline的理解。
1、結構設計
Netty中的Pipeline本質上是一個雙向鏈表,它采用了責任鏈模式。在Netty中每個Channel都有且僅有一個ChannelPipeline與之對應,它們的組成關系如下圖所示。
NEW
通過上圖可以看到,一個Channel包含了一個ChannelPipeline,而ChannelPipeline中又維護了一個由ChannelHandlerContext組成的雙向鏈表。這個鏈表的頭叫HeadContext,鏈表的尾叫TailContext,并且每個ChannelHandlerContext中又關聯著一個ChannelHandler。
2、工作原理
首先來看這樣一段代碼:
NEW
Bootstrap client = new Bootstrap(); client.channel(NioSocketChannel.class) .handler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { //接收課客戶端請求的處理流程 ChannelPipeline pipeline = ch.pipeline(); //對象編碼器 pipeline.addLast("encoder",new ObjectEncoder()); //對象解碼器 pipeline.addLast("encoder",new ObjectDecoder()); } });
對于用過Netty的小伙伴來說,應該非常熟悉。在Netty中,Pipeline的初始化,是通過調用Channel的handler()方法,然后在handler()方法中傳入一個叫做ChannelInitializer的對象,通過SocketChannel構建出一個新的Pipeline對象。每次調用addLast()方法,都會在Pipelie的末端插入一個ChannelHandlerContext。如圖所示:
NEW
每個Context中又會包含一個ChannelHandler,我們通過addLast()方法往Pipeline中添加的對象,并且Handler的添加順序會影響代碼的執行順序。而這些Handler本質上都是實現編碼和解碼的功能,不管是編碼器還是解碼器都必須實現ChannelHandler接口。
圖中的Handler就是我們代碼程序要執行的邏輯。而Netty默認幫我們實現了非常多內置Handler,我們只需要直接拿過來用就可以了。當然,我們也可以自己實現ChannelHandler接口,來實現自定義的編、碼器。比如自定義通信協議等等。
當所有的Handler全部添加到Pipeline中以后,Netty就會將這些Handler組裝成一個雙向鏈表,從而實現串行化調用。從頭部往尾部執行的Handler被稱為Inbound,用來接收用戶請求,從尾部往頭部執行的Handler被稱為Outbound,用來給用戶響應。所以,Inbound可以用來實現解碼的功能、而Outbound可以用來實現編碼的功能。
好了,以上就是我對Pipeline設計原理的理解。