Pipeline模式(netty源碼死磕6)

精進篇:netty源碼死磕6  html

巧奪天工——Pipeline模式揭祕設計模式


1. 巧奪天工——Pipeline模式揭祕

1.1. Pipeline模式簡介

管道的發名者叫,Malcolm Douglas McIlroy,他也是Unix的建立者,是Unix文化的締造者之一。架構

40年前,Unix操做系統橫空出世,Unix不只僅帶來了一個操做系統,還創造C語言,Socket,開源,黑客等等文化,這些文化影響着整個計算機世界的文明,直到今天。app

若是說Unix是計算機文明中最偉大的發明,那麼,Unix下的Pipe管道就是跟隨Unix所帶來的另外一個偉大的發明。管道的出現,解決的就是讓不一樣功能的程序能夠互相連統統訊,從而可讓軟件開發,程序開發更加的「高內聚,低耦合」,從而可讓程序「Do one thing, Do it well」,從而可讓程序「Keep it Simple Stupid」等等,這一哲學引影了一代又一代的軟件架構,直到今天的雲計算。ide

管道模型,是一種「鏈式模型」,用來串接不一樣的程序或者不一樣的組件,讓它們組成一條直線的工做流。這樣給定一個完整的輸入,通過各個組件的前後協同處理,獲得惟一的最終輸出。編碼

1.2. Pipeline模式應用場景

簡單的說,管道模型的典型應用場景,能夠用一個形象的比方,有點相似像富士康那麼的工廠生產線。雲計算

管道模型包含兩個部分:pipeline 管道、valve 閥門。操作系統

pipeline 管道,能夠比做車間生產線,在這裏可認爲是容器的邏輯處理總線。設計

valve 閥門,能夠比做生產線上的工人,負責完成各自的部分工做。 閥門也能夠叫作Handler 處理者。netty

1.3. Tomcat中的Pipeline模式

在咱們很是熟悉的Web容器Tomcat中,一個請求,首先被Connector接受到。而後,會將請求交給Container,Container處理完了以後將結果返回給Connector 。

Tomcat中,Container包含了Engine、Host、Context、Wrapper幾個內部的子容器元素。

這幾個子容器元素的功能,贅述以下:

Engine:表明一個完整的 Servlet 引擎,能夠包含多個Host。它接收來自Connector的請求,並決定傳給哪一個Host來處理,獲得Host處理完的結果後,返回給Connector。

Host:表明一個虛擬主機,一個Host能運行多個應用,它負責安裝和展開這些應用,每一個Host對應的一個域名。

Context:一個Context表明一個運行在Host上的Web應用

Wrapper: 一個Wrapper 表明一個 Servlet,它負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收。

wps8A0D.tmp

在一個用戶請求過來後,Tomcat中的每一級子容器,都對應於一個閥門Valve(注意:這個單詞不是value,有一個字母的差異)。Tomcat接受請求以後,請求從被接受,被分發,被處理,到最後轉變成http響應,會經過以下的閥門序列。


wpsE81D.tmp

這些閥門(Valve)經過invoke(next)方法彼此串聯起來,最終構成的執行順序,構成一個管道。

Pipeline模式,在設計模式中,屬於責任鏈模式的一種。在Tomcat的Pipeline模式中。從Engine到Host再到Context一直到Wrapper,都是經過同一個責任鏈,來傳遞請求。

1.4. Netty中的Pipeline模式

看完前面的《Netty 源碼(ChannelHandler 死磕)》一文,你們對Netty的Pipeline已經有初步的瞭解。

這裏再簡單的回顧一下。

一個Channel,擁有一個ChannelPipeline,做爲ChannelHandler的容器。

可是一個ChannelHandler,不能直接放進Pipeline中,必須包裹一個AbstractChannelHandlerContext 的上下文環境。

在初始化Netty的Channel時,須要將Handler加載到Pipeline中。

假定加載三個Handler,分別負責解碼、業務、編碼。三個Handler加載到ChannelPipeline的參考代碼以下:

@Override
public void initChannel(SocketChannel ch) throws Exception
{
    ChannelPipeline p = ch.pipeline();
    p.addLast(new DecoderHandler());
    p.addLast(new BusinessHandler());
    p.addLast(new EncoderHandler());
}

Netty中Channel加完Hander以後,Pipeline的容器內容圖以下:

wps4A81.tmp

Pipeline中不直接加入Handler,而是須要進行包裹。對應於Decoder、Business、Encoder三個Hander,分別建立三個默認的上下文包裹器(DefaultContext )。DefaultContext 的具體實現類,在Netty中,是DefaultChannelHandlerContext。

除此以外,Pipeline的頭尾,各有一個特別的上下文Context 。這兩個Hander Context ,不是默認的DefaultContext 。分別有本身的類型。

1.5. Context的類型

在Pipeline中頭尾,分別各有一個特別的HandlerContext——簡稱Head和Tail。Head的類型是HeadContext。Tail的類型是TailContext。這兩種類型,和DefaultChannelHandlerContext類型,都是AbstractChannelHandlerContext的子類。

wpsABAD.tmp


Head和做用是什麼呢?

Head上下文包裹器的主要做用: 主要是做爲入站處理的起點。數據從Channel讀入以後,一個入站數據包從Channel的事件發送出來,首先從Head開始,被後面的全部的入站處理器,逐個進行入站處理。

大體的入站流程以下圖:

wpsDD3.tmp

注意,TailContext,其實也是一個入站處理器。先按下不表,待會詳細闡述。

Tail的做用是什麼呢?

Tail上下文包裹器的主要做用: 主要是做爲出站處理的起點。當全部的入站處理器,都處理完成後,開始出站流程。須要出站的數據包,首先從Tail開始,被全部的出站處理器上下文Context中的Hander逐個進行處理。而後將處理結果,寫入Channel中。

wps63B4.tmp

注意,HeadContext,其實也是一個出站處理器。先按下不表,待會詳細闡述。

Tail和Head內部,沒有包裹其餘的內部Handler成員。這一點,是與默認的上下文包裹器DefaultChannelHandlerContext不一樣的地方。

TailContext自己實現了ChannelInboundHandler 接口的方式,能夠完成入站處理的操做,做爲一個入站處理器使用。

HeadContext自己,實現了ChannelOutboundHandler 接口的方式,能夠完成出站處理的操做,完成最終的出站處理操做。


1.6. Pipeline模式的優勢:

總結一下Pipeline模式的優勢,以下:

一、下降耦合度。它將請求的發送者和接收者解耦。

二、簡化了Handler處理器。使得處理器不須要不須要知道鏈的結構。也就是Handler處理器能夠是無狀態的。與責任鏈(流水線)相關的狀態,交給了Context去維護。

三、加強給對象指派職責的靈活性。經過改變鏈內的成員或者調動它們的次序,容許動態地新增或者刪除責任。

四、 增長新的請求處理器很方便。

1.7. 小結

本節從宏觀上,解讀了什麼是Netty的pipeline。

下一篇:Pipeline的入站流程和出站流程

相關文章
相關標籤/搜索