簡談分佈式計算和本地計算的區別

版權歸作者所有,任何形式轉載請聯繫作者。
作者:tison(來自豆瓣)
來源:https://www.douban.com/note/720831988/

古老的論文《A Note on Distributed Computing》介紹了分佈式計算(Distributed Computing)和本地計算(Local Computing)的四點主要的差別,批評了遠程方法調用(Remote Method Invocation)對區分不同計算類型的無力,提出了要明確區別分佈式計算與本地計算的觀點。

這篇論文出產與 1994 年,當時正是 RPC 和 RMI 大行其道的時候。軟件開發者試圖以一個模型統一所有的開發,提出將面向對象擴展到分佈式的計算環境中,使得對象訪問無需區分對象是一個本地對象或是遠程對象。這種 Slogan 乍一聽很有誘惑力,但是不同於 Truffle Framework 的通用訪問對不同語言的對象訪問的遮蔽,本地和遠程對象的訪問機制遠遠不是不同語言帶來的語義差異,還有更基礎的差別,使得試圖遮蔽本地方法調用和遠程方法調用會掩蓋一些分佈式系統固有的問題。

其之一,是調用延遲(Latency)的問題。這一點是顯而易見的,因爲調用一個本地的方法不需要走網絡,而訪問一個遠程的對象需要進行網絡通信。這使得代碼中相似的兩個方法調用其性能分析可能是大不相同的,而這種差異很難體現在代碼層面上。然而,延遲的問題只是一種表徵,我們還是可以期望硬件的升級能帶來性能的進步。延遲問題並不會導致更嚴重的程序正確性問題。

其之二,是內存訪問(Memory Access)的差異。這一點在點破之後也是顯而易見的,即一個本地的引用傳輸到遠端進程上,這個引用基本上就是無效的。一個現代的例子是 Akka 框架下的 ActorRef,本地的引用在序列化時轉化爲對應的路徑,在遠端進程中根據具體的 ActorSystem 環境再次由 ActorProvider 從路徑中產生。傳遞引用的無效性是因爲引用通常與本地的狀態,尤其是地址空間相關。一個與本地狀態關聯,指向本地對象的引用,在遠端進程中根本是無意義的。這一點首先啓發我們應該在網絡通信中傳遞值信息,同時也說明了要在應用層面遮蔽引用的不同需要額外的工作。如果不加區分的將這種工作應用在本地對象和遠程對象上,那麼本地對象的訪問開銷就會有不必要的部分。

其之三,是部分失敗(Partial Failure)的問題,即由於分佈式計算沒有一個統一的失敗機制與資源管理器(在本地環境下,可以是操作系統),計算的失敗是難以察覺、辨明和恢復的。典型的場景是進程 A 請求進程 B 執行一個動作,如果進程 A 收到進程 B 的回覆,那麼它可以知道動作已經完成。但是如果進程 A 沒有收到進程 B 的回覆,那麼進程 A 是不知道這是由於自己的信息沒有發送過去,還是進程 B 執行時失敗,還是進程 B 完成動作後的反饋丟失的。這種問題是客觀存在的,試圖遮蔽它,如果是全部認爲是本地調用,那麼系統將會在部分失敗發生時卡死或宕機;如果全部認爲是可能發生部分失敗的遠程調用,那麼對於本地調用仍然有不可避免的開銷。

其之四,是併發(Concurrency)的問題。分佈式計算中的遠程調用潛在的是併發的,同樣的,不加區分的對本地方法調用和遠程方法調用統一建模,如果忽視併發性,則一個遠程方法調用可能會永遠不返回;如果全部假設爲潛在併發的,則本地方法調用會帶來額外的複雜性。

綜上所述,問題並不在於性能下降或者程序失敗,而在於強調必須正視分佈式計算與本地計算在模型上的差別,區分不同的場景以對不同的需求進行適當的權衡與建模。

關於第二點,其中講到的 Akka 的例子也已經很清楚了,同樣的努力還發生在 gRPC 等框架中。對於遠程方法調用產生的引用失效問題,最關鍵的點是程序員需要對它有認知。我在處理 FLINK-11603 的時候,一開始試圖將一個本地的 Gateway 直接序列化傳送到遠程,這實際上是一個裸地發送 ActorRef 的行爲。後來在瞭解到引用失效的問題之後,改爲傳送路徑名的值對象,在遠端根據這個值重新建立起連接並獲得 Gateway。

關於第三點,可以參考這篇文章《Nobody Needs Reliable Messaging》(https://www.infoq.com/articles/no-reliable-messaging/)。把遠程調用【就這麼】認爲是本地調用會導致嚴重的正確性問題,首先是需要區分本地調用和遠程調用。但是對於遠程調用我們選擇提供何種程度的可靠性,這仍然是一個值得探討的問題。

關於第四點,併發是新時代軟件開發者怎麼也繞不過去的議題。本地調用中的 IO 操作也可能需要併發來減少阻塞,甚至單純的計算操作也可以通過並行發送到不同的核同時計算以提高性能。當然,對於一些不存在併發的簡單調用,我們不需要引入併發上下文。這一點仍然是要求軟件開發者對何時應該併發要有一個準確的認識。

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