Netty的ChannelPipeline
1、如何理解Netty的ChannelPipeline
在Netty中,每個Channel被創建的時候都需要被關聯一個對應的pipeline(通道),這種關聯關係是永久的(整個程序運行的生命週期中)。ChannelPipeline可以理解成一個消息( 或消息事件,ChanelEvent)流轉的通道,在這個通道中可以被附上許多用來處理消息的handler,當消息在這個通道中流轉的時候,如果有與這個消息類型相對應的handler,就會觸發這個handler去執行相應的動作。它實現了Intercepting
Filter模式(個人理解與Filter Chain模式類似)。
可以通過下面這句話來理解一些相關的概念:ChannelEvents are processed by ChannelHandlers in a ChannelPipeline
2、ChannelPipeline的創建方式
Netty的作者建議採用輔助類org.jboss.netty.channel.Channels的靜態無參函數pipeline來創建一個ChannelPipeline對象,從源代碼上看其實就是調用了DefaultChannelPipeline的無參構造函數,返回new出來的對象而已。
3、消息的流轉
Netty中消息的流轉有兩個方向:上行、下行
因此,處理消息事件(ChannelEvent)的處理器(ChannelHandler)大致可以分爲兩個方向:ChannelUpstreamHandler、ChannelDownstreamHandler
* I/O Request
* via {@link
Channel} or
* {@link ChannelHandlerContext}
* |
* +----------------------------------------+--------------- +
* | ChannelPipeline | |
* | \|/ |
* | + ----------------------+
+----------- +------------+
|
* | | Upstream Handler N | | Downstream Handler 1 | |
* | + ----------+----------- +
+-----------+ ------------+
|
* | /|\ | |
* | | \|/ |
* | + ----------+----------- +
+-----------+ ------------+
|
* | | Upstream Handler N -1
| | Downstream Handler 2 | |
* | + ----------+----------- +
+-----------+ ------------+
|
* | /|\ . |
* | . . |
* | [ sendUpstream() ] [ sendDownstream() ] |
* | [ + INBOUND data ] [ + OUTBOUND data ] |
* | . . |
* | . \|/ |
* | + ----------+----------- +
+-----------+ ------------+
|
* | | Upstream Handler 2 | | Downstream Handler M -1
| |
* | + ----------+----------- +
+-----------+ ------------+
|
* | /|\ | |
* | | \|/ |
* | + ----------+----------- +
+-----------+ ------------+
|
* | | Upstream Handler 1 | | Downstream Handler M | |
* | + ----------+----------- +
+-----------+ ------------+
|
* | /|\ | |
* +-------------+ --------------------------+--------------- +
* | \|/
* +-------------+ --------------------------+--------------- +
* | | | |
* | [ Socket.read() ] [ Socket.write() ] |
* | |
* | Netty Internal I/O Threads (Transport Implementation) |
* +--------------------------------------------------------+
以upstream爲例,從socket讀出來的數據,逐漸往上進行傳遞,即原始數據依次往上被進行解析,可能因爲所需要的業務數據外面包裹着許多其它附加的數據。如加密、驗證、簽名等。
downstream與此相反,即把業務數據進行一層層地加密、簽名等處理後,寫到socket中發出去。這個模型其實可以參考(TCP的七層模型)
4 、pipeline中的handlers順序如何理解
在添加handler的時候,如果理解順序。可以把pipeline理解成一個隊列,addLast是添加到隊列的尾部,addFirst是添加到隊列的頭部。
upstream的方向是從頭到尾,downstream的方向是從尾到頭。
5、 多線程環境
ChannelPipeline中的handler是可以在任何時候動態地增加或者刪除的,因爲ChannelPipeline本身是線程安全的(這點由Netty本身去保證)
6、 ChannelPipeline實例具體解析
在對ChannelPipeline進行解析時,以Netty提供的一個默認實現DefaultChannelPipeline來進行解析,先來看下這個類的一些成員變量(去除日誌相關成員logger)
static final ChannelSink
discardingSink = new DiscardingChannelSink();
private volatile Channel channel;
private volatile ChannelSink
sink;
private volatile DefaultChannelHandlerContext
head;
private volatile DefaultChannelHandlerContext
tail;
private final Map<String,
DefaultChannelHandlerContext> name2ctx =
new HashMap<String,
DefaultChannelHandlerContext>(4);
discardingSink是用來處理上行到最上,或者下行到最下時的對消息事件的處理,這個可以不用太關注
主要來關注下head、tail、name2ctx,head和tail這一看就是鏈表的頭和尾,可以進一步猜想pipeline中的handlers是按照一個鏈表排列的。name2ctx用一個map結構提供名稱到handler的映射關係(通過handlerContext可以找到相應的handler)。
下面以addLast爲例來進行解析
public synchronized void addLast(String
name, ChannelHandler handler) {
if (name2ctx.isEmpty())
{
init(name, handler);
} else {
checkDuplicateName(name);
DefaultChannelHandlerContext oldTail = tail;
DefaultChannelHandlerContext newTail = new DefaultChannelHandlerContext(oldTail, null,
name, handler);
callBeforeAdd(newTail);
oldTail.next = newTail;
tail = newTail;
name2ctx.put(name, newTail);
callAfterAdd(newTail);
}
}
依賴DefaultChannelHandlerContext來實現隊列結構,在DefaultChannelHandlerContext中有指向前一個和後一個的引用,就不細看,只用看一個DefaultChannelHandlerContext的成員變量即可。
private final class DefaultChannelHandlerContext implements ChannelHandlerContext
{
volatile DefaultChannelHandlerContext next;
volatile DefaultChannelHandlerContext prev;
private final String
name;
private final ChannelHandler
handler;
private final boolean canHandleUpstream;
private final boolean canHandleDownstream;
private volatile Object
attachment;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.