請放棄RPC!分散式程式設計第一謊言:網路是可靠的 - David Boike

banq發表於2019-08-07

與幾十年前相比,網路相當可靠,隨著我們繼續構建更大,更全球分佈的系統,我們使自己容易受到可能發生的所有不良事件的影響。
為了解決這個問題,我們將不得不放棄同步請求/響應型別程式設計。呼叫方法(稱為遠端過程呼叫或RPC)的物件導向模型傾向於分解為網路不可靠時的條件,將我們的系統置於非確定性狀態,這是非常難以擺脫的狀態。

現象
請看兩個事故:
我們上網的ISP有兩個路由器:主路由器和備用路由器。如果有一天,主路由器出現故障。需要切換到備份,卻發現其路由表在很長一段時間內沒有更新,這導致大部分人無法上網。
另一種情況:專案使用Oracle資料庫。一切在開發環境中都很有效,但在生產中還有一個額外的負載均衡器和防火牆。每隔一段時間,負載均衡器就會默默地將連線到資料庫的TCP丟棄,但是這些錯誤的連線繼續位於連線池中,因此下次需要連線時,就會得到一個意外拋錯。
就在最近,6月12日,亞洲的一家網際網路服務提供商在全球大部分地區打破了網際網路,在歐洲引發了網際網路問題。還有twitter Facebook google等同時出現大面積斷網。
一般而言,無論是本地還是全球,您都不能信任任何網路。硬體,軟體和安全性都可能導致問題。這在分散式計算的第一個謬論中被編纂:網路是可靠的。
這對於HTTP通訊或任何請求/響應或遠端過程呼叫(RPC)通訊型別尤其成問題。

解決方案
要提供真正可靠的系統,您必須接受並非總是可以進行跨網路通訊。因為我們無法保證通訊嘗試能夠成功,所以我們需要提供一種在故障後自動重試的工具。為了防止在重試期間出現故障,我們可以使用名為store and forward的模式。我們可以將資料儲存在本地儲存中,而不是直接將資料傳送到遠端伺服器。這樣,當我們再次啟動時,我們就準備好繼續我們離開的地方。我們可以使用事務來確保我們繼續重試,直到處理成功。
這超出了圍繞Web服務呼叫的簡單重試迴圈的級別,如果伺服器在崩潰時執行,則會失敗。我們需要額外的基礎設施來實現這些保障

非同步訊息傳遞
有許多不同的技術,稱為可靠訊息傳遞或訊息排隊系統,可以解決這些型別的問題。在Microsoft平臺上,最著名的是Microsoft訊息佇列(MSMQ),在Azure上,有Azure Queue StorageAzure Service Bus。在Microsoft生態系統之外,有RabbitMQActiveMQZeroMQ。基本上任何帶有“MQ”的東西都表明該產品符合這一系列技術。
這些排隊技術將諸如Web服務呼叫之類的東西包含在稱為訊息的孤立的,離散的工作單元中。訊息佇列使用儲存和轉發來確保訊息到達它需要的位置。它可以促進自動重試,因為即使在系統崩潰之後也可以反覆嘗試訊息處理。有些甚至支援事務,因此只有在業務事務成功時才會完全使用訊息。這樣,可以保證每個訊息只成功處理一次。

與簡單的重試迴圈相比,排隊技術具有額外的優勢。例如,如果我們試圖建立一個客戶並收到HTTP超時,我們將無法知道伺服器是否收到了資料並且根本無法響應,或者是否相反,資料根本沒有到達。

重試帶來了伺服器端複製的可能性。如果我們重新嘗試建立客戶,我們可能會意外地建立客戶兩次。

訊息佇列帶有訊息ID的概念,以便伺服器可以決定嘗試是否是重試。實質上,訊息傳遞允許在伺服器端進行重複資料刪除。

放棄請求/響應
非同步訊息傳遞需要稍微改變思路,因為它不能提供執行典型Web服務呼叫中看到的傳統請求/響應的能力。
將訊息傳送到訊息佇列是一種即發即棄的操作。您將訊息放入佇列中,最終它將進入伺服器,伺服器將處理它。您沒有在下一行程式碼上獲得立即返回值。
最終,透過解決某些基礎架構問題,非同步訊息傳遞會迫使您重新設計系統的邏輯流程。
這是排隊技術的艱難飛躍:並不是說他們有一個難以使用的API(他們沒有),但他們需要放棄更傳統的請求/響應程式設計模型。
不幸的是,你不能只使用HTTP系統,插入佇列並運送它。它需要對系統進行重大的重新設計,有時需要重寫。
這可能很嚇人,但結果是值得的。

(banq注:這也是CAP定理的由來,CAP是分散式系統黃金定律,沒有人能夠逃脫其三選二,CAP其中有一個P分割槽容錯,就是針對分散式網路的不可靠造成腦裂分割槽的容忍度,如果你需要P,那麼只能C和A之間選擇,但是普通人只會忽視P,選擇CA,這也是關聯式資料庫的特點,當人們處於一個世界舒適久了,忘記更大的世界,)

相關文章