Pipeline模式(netty源碼死磕6)

精進篇:netty源碼死磕6 

巧奪天工——Pipeline模式揭祕


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

1.1. Pipeline模式簡介

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

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

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

管道模型,是一種“鏈式模型”,用來串接不同的程序或者不同的組件,讓它們組成一條直線的工作流。這樣給定一個完整的輸入,經過各個組件的先後協同處理,得到唯一的最終輸出。

1.2. Pipeline模式應用場景

簡單的說,管道模型的典型應用場景,可以用一個形象的比方,有點類似像富士康那麼的工廠生產線。

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

pipeline 管道,可以比作車間生產線,在這裏可認爲是容器的邏輯處理總線。

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

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的參考代碼如下:

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模式的優點,如下:

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

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

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

4、 增加新的請求處理器很方便。

1.7. 小結

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章