看過前面的架構議題後,一個自然的問題是:中介軟體在其中的位置是什麼? 中介軟體是介於應用程式與分散式平台之間的一層,重要目的在提供一定程度的分散透明性——對應用程式隱藏資料、處理與控制的分散。
中介軟體與架構風格#
- 實務上常見中介軟體系統本身遵循某種特定的架構風格:例如 CORBA 採物件式風格,TIB/Rendezvous 則採事件式風格。
- 好處:中介軟體貼合某種風格,應用程式的設計可以變簡單。
- 明顯的缺點:中介軟體可能不再是應用開發者心中最理想的形狀。例如 CORBA 起初只提供可被遠端呼叫的物件,後來認為只有這種互動太受限,才加入訊息傳遞等其他互動模式——而不斷加功能很容易讓中介軟體臃腫(bloated)。
雖然中介軟體的本意是提供分散透明性,但普遍認為具體方案應能依應用需求調適。一種解法是為不同應用類別做不同版本的中介軟體;公認更好的做法是把中介軟體做得容易配置、調適與客製。因此現今的系統開發更嚴格地區分政策(policy)與機制(mechanism),並發展出數種修改中介軟體行為的機制。
攔截器(interceptors)#
概念上,攔截器不過是一種打斷正常控制流、讓其他(應用專屬)程式碼得以執行的軟體構造。要把攔截器做得通用可能需要可觀的實作工夫,是否值得為通用性犧牲簡單性並不明朗;很多時候,只提供有限的攔截功能反而讓軟體與整個系統更好管理。
以物件式分散式系統為例。物件 A 呼叫位於另一台機器的物件 B 的方法,這種遠端物件呼叫分三步:
- A 拿到一個與 B 的介面完全相同的本地介面,直接呼叫其中的方法。
- 該呼叫被轉換成通用物件呼叫——透過 A 所在機器的中介軟體提供的通用物件呼叫介面。
- 通用物件呼叫再被轉換成訊息,經 A 的本地作業系統提供的傳輸層網路介面送出。
攔截器可以插在其中兩處:
- 請求層攔截器(request-level interceptor):假設 B 被複寫(replicated),每個複本都該被呼叫。攔截器只要對每個複本各呼叫一次通用呼叫即可——A 不必知道 B 被複寫,物件中介軟體也不需要專門處理複寫呼叫的元件,只有攔截器需要知道。
- 訊息層攔截器(message-level interceptor):協助把呼叫傳到目標物件。例如參數其實是巨大的資料陣列時,可在此把資料切成小段、在目的地重組,以改善效能或可靠性;中介軟體同樣不需要知道切割的存在。

圖 2-15:使用攔截器處理遠端物件呼叫。
攔截器的精髓是把橫向能力(複寫、切割、記錄……)加在控制流的固定斷點上,讓應用與中介軟體核心都保持不知情。這是「政策與機制分離」的具體示範。
調適性軟體的一般做法#
攔截器提供的其實就是調適中介軟體的手段。調適的需求來自分散式應用的執行環境持續變動:行動性、網路服務品質的劇烈變化、硬體故障、電池耗盡等等。與其讓應用程式自行應對變化,不如把這件事放進中介軟體。
McKinley 等人歸納出三種達成軟體調適的基本技術:
- 關注點分離(separation of concerns):傳統的模組化思路——把實作功能的部分與處理可靠性、效能、安全等「額外功能(extra functionalities)」的部分分開。開發中介軟體很大程度上就是在獨立於應用地處理這些額外功能。問題是這些橫切關注點(cross-cutting concerns)很難用模組化乾淨切開——「把安全放進一個獨立模組」行不通,也很難想像容錯能被裝箱成獨立服務來賣。分離再織入這些關注點正是剖面導向軟體開發(aspect-oriented software development, AOSD)的主題,但剖面導向尚未成功應用於大規模分散式系統,離那個階段還有很長的路。
- 計算反射(computational reflection):程式檢視自身、必要時調整自身行為的能力。反射已內建於 Java 等語言,提供強大的執行期修改能力;部分中介軟體也支援反射技術。但與剖面導向一樣,反射式中介軟體尚未證明自己是管理大規模分散式系統複雜度的有力工具。
- 元件式設計(component-based design):透過**組合(composition)支援調適——設計期靜態配置,或執行期動態配置。後者需要晚期繫結(late binding)**支援;這項技術在程式語言環境與可任意載卸模組的作業系統中都已成功應用。執行期自動挑選元件最佳實作的研究也在進行,但對分散式系統而言過程依然複雜:替換一個元件必須先知道它對其他元件的影響,而元件往往沒有想像中獨立。
討論#
分散式系統的軟體架構——尤其是中介軟體——龐大而複雜。這很大程度來自「必須通用」的要求:要提供分散透明性,同時應用又各有與完全透明相衝突的額外功能需求。通用與特化的衝突造就了高度彈性的中介軟體方案,代價就是複雜度。
有研究報告指出:某軟體產品問世僅四年,體積就成長 50%,檔案總數更增為三倍。這顯然不是值得追求的方向。
幾個值得深思的論點:
- 既然幾乎所有大型軟體系統如今都得在網路環境中執行,可以自問:分散式系統的複雜度是不是「試圖讓分散透明化」的固有代價?開放性等議題固然重要,但對彈性的需求從未像中介軟體這樣強烈。
- Coyler 等人主張需要的是更著重(外部的)簡單性、更簡單的元件式中介軟體建構方式,以及應用獨立性。上述哪種技術是解答仍有爭論——目前沒有任何一種被大量採用,也沒有成功應用到大規模系統。
- 底層假設是「軟體應隨環境變化而改變」。但該質疑的是:環境變化真的是改動軟體的好理由嗎? 硬體故障、安全攻擊、電力耗盡……這些環境影響其實都是軟體可以(也應該)事先預期的。
- 支持調適性軟體最強、也最站得住腳的理由是:許多分散式系統不能停機。這要求元件能在線上替換與升級,但上述方案是否是解決這個維運問題的最佳解,並不清楚。
最後留下的結論是:分散式系統應能對環境變化做出反應——例如切換資源配置政策。啟用這種調適所需的軟體元件會全部就位,改變的是元件內演算法的設定,而挑戰在於讓這種反應式行為不需人為介入。這條路在討論分散式系統的實體組織(例如決定元件放哪裡)時效果更好——這正是下一節的主題。