在深入各種通訊模型之前,先回顧兩件基礎工作:一是網路通訊協定,它是任何分散式系統的基礎;二是換個角度,對分散式系統中出現的通訊型態做分類。

分層協定(Layered Protocols)#

由於沒有共享記憶體,分散式系統中的一切通訊都建立在傳送與接收(低階)訊息之上。當行程 A 要與行程 B 通訊時,A 先在自己的位址空間中組出訊息,再透過系統呼叫讓作業系統把訊息經網路送給 B。想法簡單,但為了避免混亂,A 與 B 必須對傳送位元的意義取得共識,而且需要在許多層級上達成協議:

  • 用幾伏特代表 0、幾伏特代表 1?
  • 接收端如何知道訊息的最後一個位元在哪?
  • 如何偵測訊息損毀或遺失?發現了該怎麼辦?
  • 數字、字串等資料多長、如何表示?

OSI 參考模型#

為了處理這麼多層級的議題,國際標準組織(ISO)制定了開放系統互連參考模型(Open Systems Interconnection Reference Model),通稱 OSI 模型。所謂開放系統(open system),是指準備好依循標準規則與任何其他開放系統通訊的系統;這些規範訊息格式、內容與意義的規則,正式名稱就是協定(protocol)

OSI 模型附帶的那套協定從未被廣泛使用,如今已名存實亡;但模型本身對理解電腦網路仍然非常有用。實務上真正普及的是網際網路的協定,如 TCP 與 IP。

協定分為兩大類:

  • 連線導向(connection-oriented)協定:收發雙方交換資料前必須先明確建立連線,可能還要協商所用的協定,結束後要釋放連線。電話就是連線導向的通訊系統。
  • 非連線(connectionless)協定:不需事先設置,發送方準備好就直接送出第一則訊息。把信投進郵筒即是一例。

OSI 模型把通訊分成七層,每層處理通訊的一個特定面向,並對上層提供介面(一組定義該層服務的操作)。訊息由發送端一路往下傳:每經過一層就在前面加上該層的表頭(header)(有些層還會在尾端加上 trailer),最後由實體層送上傳輸媒介;到達接收端後逐層往上,每層剝掉並檢查自己的表頭。第 n 層表頭中的資訊,就是給第 n 層協定使用的。

圖 4-2:一則典型訊息在網路上出現時的樣貌

延伸案例:航空公司與外燴商的兩層協定

考慮 Zippy 航空與外燴商 Mushy Meals 的往來。每個月 Zippy 的旅客服務主管請祕書聯絡 Mushy 業務經理的祕書訂購十萬份橡皮雞餐盒。原本訂單走郵局,後來郵政服務品質下滑,兩位祕書決定改用電子郵件——不必驚動老闆,因為祕書層的協定只管訂單的實體傳輸,不管內容。同樣地,主管也可以把橡皮雞換成新推出的招牌羊肋排,而不影響祕書層。這裡有兩層:老闆層與祕書層,各自的協定(討論的主題與使用的技術)可以獨立更換——這種各層可隨技術演進獨立替換而互不影響的獨立性,正是分層協定吸引人的原因。

一個系統所使用的一組協定,稱為協定套組(protocol suite)協定堆疊(protocol stack)。要注意區分參考模型與其實際協定:OSI 協定從未流行,以下逐層介紹時,會改以各層對應的網際網路協定為例。

低階協定#

最底下三層合起來實作了電腦網路的基本功能:

  • 實體層(physical layer):負責傳送 0 與 1。關心用幾伏特表示 0/1、每秒可送幾個位元、能否雙向同時傳輸,以及接頭的大小形狀、腳位數量與意義等。實體層協定把電氣、機械與信號介面標準化,確保一方送出的 0 位元在另一方也被收成 0;例如序列通訊線的 RS-232-C 標準。
  • 資料連結層(data link layer):實體層只管送位元,但真實網路會出錯,因此需要偵錯與更正機制,這是資料連結層的主要任務。它把位元組成訊框(frame),在每個訊框頭尾放上特殊位元樣式做記號,並計算**檢查和(checksum)**附在訊框上;接收端重算檢查和比對,不符就要求重傳。訊框帶有序號,以便辨識。
  • 網路層(network layer):在 LAN 上發送者通常不必定位接收者,但廣域網路由大量機器與線路構成,訊息可能要經過多個中繼跳點,每一跳都得選擇出線。如何選出最佳路徑稱為繞送(routing),這正是網路層的主要任務。最短路徑不一定最好——真正重要的是路徑上的延遲,而延遲又與流量及排隊訊息量有關,會隨時間變化;有些繞送演算法會嘗試適應負載變化,有些則依長期平均做決策。目前最廣泛使用的網路層協定是非連線的 IP(Internet Protocol):每個 IP 封包不需設置即可送出,各自獨立繞送到目的地,不會選定並記住內部路徑。

傳輸協定#

**傳輸層(transport layer)**是「基本網路協定堆疊」的最後一塊:它補齊網路層介面沒有提供、但建構網路應用合理需要的服務——換句話說,傳輸層把底層網路變成應用開發者真正可用的東西。

  • 封包在途中可能遺失。傳輸層的工作是提供可靠連線:應用層把訊息交給傳輸層,就能預期它會不遺失地送達。
  • 傳輸層收到應用層訊息後,把它切成足夠小的片段、逐一編上序號後送出。傳輸層表頭裡談的就是哪些封包已送出、已收到、接收端還有多少空間、哪些要重傳等事項。
  • 可靠的傳輸連線(依定義是連線導向的)可以建立在連線導向或非連線的網路服務上。後者的封包可能各走不同路徑而亂序到達,由傳輸層軟體負責重新排序,維持「傳輸連線像一根大管子——訊息放進去,會完好且依序地出來」的假象。提供這種**端對端(end-to-end)**行為是傳輸層的重要面向。

網際網路的傳輸協定是 TCP(Transmission Control Protocol);TCP/IP 組合如今是網路通訊的事實標準。協定套組中另有非連線的傳輸協定 UDP,本質上就是 IP 加上少量補充,供不需要連線導向協定的程式使用。此外也不斷有新的傳輸協定被提出,例如支援即時資料傳輸的 RTP(Real-time Transport Protocol)——它是一個框架協定,規定即時資料的封包格式,但不提供保證遞送的實際機制,並附帶監控 RTP 封包傳輸的協定。

高階協定#

傳輸層之上,OSI 還區分了三層,但實務上只有應用層真正被使用;網際網路協定套組更是把傳輸層以上的東西全部歸為一類。

  • 會期層(session layer):本質上是傳輸層的強化版,提供對話控制(記錄目前輪到哪一方發言)與同步設施(在長時間傳輸中插入檢查點,當機時只需退回最近的檢查點而非從頭開始)。實務上很少應用在意會期層,網際網路協定套組甚至沒有它;不過在發展中介軟體方案時,「會期」概念及其協定其實相當有用,尤其是在定義高階通訊協定時。
  • 展示層(presentation layer):下層關心的是把位元可靠且有效率地送達,展示層關心的則是位元的意義。多數訊息不是隨機位元串,而是姓名、地址、金額等結構化資訊;展示層可以定義包含這類欄位的紀錄,讓發送方告知接收方訊息內含某種格式的紀錄,方便內部表示法不同的機器彼此溝通。
  • 應用層(application layer):原本打算收納電子郵件、檔案傳輸、終端機模擬等標準網路應用,如今變成一切「放不進下層」的應用與協定的容器。從 OSI 參考模型的角度看,幾乎所有分散式系統都只是應用。

這個模型缺少的是應用、應用特定協定、通用協定三者的清楚區分。例如網際網路的檔案傳輸協定 FTP 定義了客戶端與伺服器間傳檔的協定,不應與 ftp 程式(實作了 FTP 的終端使用者應用)混為一談。又如 HTTP(HyperText Transfer Protocol)原是為遠端管理與傳輸網頁而設計、由瀏覽器與網頁伺服器實作的應用特定協定,如今卻也被與 Web 無關的系統採用——例如 Java 的物件呼叫機制用 HTTP 來請求呼叫防火牆後的遠端物件。同時,還有許多對眾多應用都有用、卻不能算傳輸協定的通用協定,它們多半屬於接下來要談的中介軟體協定。

中介軟體協定#

中介軟體是邏輯上(大多)位於應用層的應用,但其中含有許多值得自成一層的通用協定,獨立於更特定的應用之外。可分為「建立各種中介軟體服務的協定」與「高階通訊協定」兩類。

支援中介軟體服務的協定例子:

  • 鑑別(authentication)協定:提供宣稱身分的證明;不與特定應用綁死,可整合進中介軟體作為通用服務。授權(authorization)協定(讓通過鑑別的使用者與行程只能存取有權限的資源)同樣具有一般性。
  • 分散式提交(distributed commit)協定:確保一群行程要嘛全部執行某項操作、要嘛全都不執行,也就是原子性(atomicity),廣泛用於交易,容錯應用也能受益。
  • 分散式鎖定(distributed locking)協定:保護資源不被分散在多台機器上的行程同時存取。

中介軟體通訊協定則支援高階通訊服務,例如:以高度透明的方式呼叫遠端機器上的程序或物件;為即時資料設定與同步串流;可擴展到廣域網路上數千個接收者的可靠多播服務。有些中介軟體通訊協定其實也可以放在傳輸層,但保留在較高層可能有特定理由——例如可靠多播若要保證可擴展性,只有把應用需求納入考量才做得到,因此中介軟體系統可能提供多種(可調校的)協定,各自以不同傳輸協定實作,但對外提供單一介面。

依這種分層思路,可以得到一個調整後的參考模型:與 OSI 相比,會期層與展示層被單一的中介軟體層取代,其中放的是與應用無關的協定,位於傳輸層之上、應用層之下。原有的傳輸服務也可以不加修改地作為中介軟體服務提供,中介軟體通訊服務也可能包含與傳輸層相當的訊息傳遞服務。

圖 4-3:網路通訊的調整後參考模型

本章接下來聚焦四種高階中介軟體通訊服務:遠端程序呼叫、訊息佇列服務、連續媒體串流的通訊支援,以及多播。

通訊的類型#

要理解中介軟體能提供哪些通訊選項,可以把中介軟體視為客戶端—伺服器運算中的一項額外服務:應用透過中介軟體這個中間(分散式)服務彼此通訊。以電子郵件系統為例:郵件遞送系統的核心可以視為一種中介軟體通訊服務——每台主機執行使用者代理程式供使用者撰寫、傳送與接收郵件;發送端把郵件交給遞送系統,期待它終究把郵件送達收件者;接收端的使用者代理程式則連上遞送系統查看是否有新郵件。

圖 4-4:把中介軟體視為應用層通訊中的中間(分散式)服務

持久性區分:

  • 持久通訊(persistent communication):訊息一旦提交傳送,就由通訊中介軟體保存,直到送達接收者為止。因此發送應用提交訊息後不必繼續執行,接收應用在訊息提交當下也不必在執行。電子郵件是典型例子。
  • 暫時通訊(transient communication):訊息只在收發雙方的應用都在執行期間由通訊系統保存。若中介軟體因傳輸中斷或接收方不在線而無法遞送,訊息就直接丟棄。傳輸層的通訊服務通常都只提供暫時通訊,此時通訊系統就是傳統的儲存轉送(store-and-forward)路由器:路由器無法把訊息交給下一站或目的主機時,就把它丟掉。

同步性區分:

  • 非同步通訊(asynchronous communication):發送者提交訊息後立即繼續執行,訊息在提交當下(暫時)存放於中介軟體。
  • 同步通訊(synchronous communication):發送者阻塞,直到確知請求已被接受。同步點有三種可能:
    1. 阻塞到中介軟體通知它將接手傳送該請求為止;
    2. 阻塞到請求已送達接收者為止;
    3. 阻塞到請求被完整處理完畢、接收者回傳回應為止。

實務上常見的組合:持久+提交時同步是許多訊息佇列系統的常見方案;暫時+處理完畢後同步則對應遠端程序呼叫(RPC)。兩者都會在本章後續詳述。

最後還要區分**離散(discrete)串流(streaming)**通訊:

  • 離散通訊:通訊雙方以訊息往來,每則訊息是一個完整的資訊單位。前述例子都屬此類。
  • 串流通訊:連續送出多則訊息,訊息之間因發送順序或時間關係而彼此相關。本章後面會深入討論。