詳細解讀微服務的兩種模式
來自專欄騰訊雲+社區6 人贊了文章
歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~
本文來自雲+社區翻譯社,由用戶1196457編譯。
微服務是一種架構範例。在這種架構中,多個小型獨立組件協同工作,從而構成一個系統。儘管它的操作複雜性較高,但這種範式已經被迅速採用。這是因為它有助於將複雜的系統分解為可管理的服務。這些服務更關注微觀層面的問題,包括單一責任,關注點分離,模塊化等。
微服務模式是一個系列博客。每篇博文都將聚焦一種微服務的架構模式,分析其可行性並概述它們適用的場景。所有這一切都要遵守各系統間相互制約的設計約束。
服務間通信和執行流程是分散式系統的基礎,它可以是同步的也可以是非同步的。這兩種方法都有其利弊,本博客試圖詳細剖析各種選擇並分析其影響。
維度
每種實現方式都可以從多種維度進行權衡。從這些維度對權衡點和系統約束進行評估,有助於我們分析其可行性和適用性。每種實現方式都有折衷。與此同時,考慮中的系統可能有各種各樣的維度。根據這些限制評估取捨可以幫助我們推斷方法和適用性。系統的各個維度都會影響系統的執行流程和通信方式,下面我們來看看其中的一些維度。
消費者
系統的消費者可以是外部程序,網頁/手機介面,物聯網設備等。消費者應用程序通常會同步處理伺服器,並期望介面支持。用消費者的統一介面掩蓋分散式系統的複雜性也是可取的,必要條件是,我們的通信方式選擇能帶來便利。
工作流管理
業務工作流貫穿多個服務,因此,業務工作流的管理至關重要。它可以是隱含的,並且可以發生在每個服務上,因此仍然分布在各個服務中。換言之,它可以是明確的。協調器服務可以承擔協調業務流程的責任。編排是兩者的結合。工作流規範規定了執行順序和對服務的實際調用。協調器與參與服務遵循的通信範式緊密相關。通信風格和執行流程推動了協調器的實現。
第三個選項是基於事件編排的設計,通過一個將所有服務綁定的事件匯流排來代替編排器。
所有這些都是系統中的工作流管理機制,我們將在本系列的後續篇章詳細介紹工作流程管理。在我們評估和選擇通信方式時,我們會考慮當前上下文中與其相關的約束條件。
讀/寫頻率偏差
系統的讀/寫頻率可能是其體系結構中的關鍵因素。一個讀取繁重的系統需要大部分操作同步完成。一個很好的例子就是大規模運營的天氣預報服務的公共API。或者,寫入繁重的系統可從非同步執行中受益。一個例子就是一個平台,無數物聯網設備都在不斷報告數據。當然,它們之間也有系統。由於讀寫偏斜,有時候傾向於一種風格是有用的。在其他時候,將讀取和寫入拆分為單獨的組件可能是有意義的。
在我們審視各種方法時,我們需要保持這些約束。這些維度將幫助我們提取每種實現方式的適用性。
同步
同步通信是調用方等待響應可用的通信方式,是一個突出並得到廣泛使用的方法。簡單且直觀的概念使其適用於大多數情況。
同步通信與HTTP協議密切相關。但是,其他協議仍然是實現同步通信的合理方式。另一個很好的例子是RPC調用,每個組件都公開一個其他服務所調用的同步介面。
入口點附近的攔截器攔截業務流程請求,然後將請求推送到下游服務,所有的後續調用本質上都是同步的。這些調用可以是並行或順序的,直到處理完成。系統內的調用處理可能會有不同的方式。一個編排者可以顯式調度所有的調用,或者調用可以跨組件有機地滲透。下面我們看看幾個可能的機制。
變化
在同步系統中,架構可以採用幾種方法,以下簡要說明各種方法的可行性。
去中心化和同步
去中心化的同步通信方式在入口點攔截流量,攔截器將請求轉發到下一步並等待響應,該循環一直下行,直到所有服務都已完成執行,每個服務可以順序或並行執行一個或多個下游服務。
雖然實現很簡單,但流程細節分布在整個系統中,從而導致組件之間的耦合。
這些調用在整個系統中保持同步。因此,這種通信方式可以滿足同步消費者的期望。由於分散式工作流的性質,該方式缺少靈活性,並不適用於經常更改的複雜工作流。由於對系統的每個請求都可能阻塞服務,因此對於讀/寫頻率高的系統來說,這並不理想。
編排、同步和順序
同步通信的一種變體帶有中央編排器,編排器仍然是攔截服務。它處理傳入的工作流定義請求並將其轉發到下游服務,並接受響應(如下圖所示)。在處理請求過程中,編排器一直在對服務進行調用。
在初始約束固定的情況下,工作流管理在這種方法中更加靈活。工作流更改對編排器來說仍然是本地化的,並保有一定的靈活性,由於通信是同步的,所以同步消費者可以在沒有中介組件的情況下進行通信。但是,編排器需要持續保持所有活動請求,這使得編排器比其他服務承擔更重的責任,也容易導致單點故障。這種風格的架構仍然適合讀取繁重的系統。
編排,同步和並行
在之前的方法基礎上的一個小改進是使獨立請求可以並發,這可以獲得更高的效率和性能。由於這個責任屬於編排器,所以很容易做到。工作流管理已經集中,需要做的只是更改聲明以區分並行和順序調用。這可以提高流程執行速度,通過縮短響應時間,協調器可以獲得更高的吞吐量。
工作流管理比以前的方法更複雜,但它仍然可能是一個合理的折衷方案,因為它可以提高吞吐量和性能並同時保持消費者的通信同步。由於其同步特性,該系統對於讀取型架構來說仍然更好。
權衡
儘管同步調用更易於掌控,調試和實現,但在分散式環境中實施則需要一些權衡。
平衡能力
它要求有意平衡所有服務的能力。一個組件上的流量激增可能淹沒其他服務請求。在非同步通信中,隊列可以緩解流量激增。同步通信缺少這種中介,需要服務容量在流量激增期間進行匹配。如果做不到這一點,可能會出現級聯故障。另外,像斷路器這樣的彈性範例可以幫助緩解同步系統中的流量激增。
級聯故障的風險
同步通信使上游服務在微服務架構中容易出現級聯故障。如果下游服務出現故障或最壞情況,則需要很長時間才能回應,資源會很快耗盡。這可能會導致系統產生多米諾骨牌效應。可能的緩解策略可能涉及一致的錯誤處理,合理的超時時間以及執行服務質量保障協議。在同步環境中,一個服務會立即影響到其他服務。如前所述,通過實施艙壁架構或斷路器可防止級聯錯誤。
增加負載平衡和服務發現開銷
通過將參與服務放置在負載均衡器後面可以解決其冗餘和可用性需求。這增加了每個服務的隔離級別。此外,每項服務都需要加入中央服務發現設置,這允許它推送它自己的地址並解析下游服務的地址。
耦合
同步系統會在一段時間內表現出更緊密的耦合。服務之間沒有抽象,服務直接和其他服務的合同綁定。這在一段時間內產生了強烈的關聯。對於合同中的簡單更改,擁有的服務不得不在早期採用版本控制。它增加了系統的複雜性,或者會導致與合同相關的所有消費者服務的變化。
隨著服務網格等新興架構範例的出現,有可能解決一些陳述的問題。Istio,Linkerd,特使等工具,允許服務網格創建。這個社區正在成熟並且充滿希望,它可以幫助構建同步的,解耦的和容錯的系統。
非同步
非同步通信非常適合分散式體系結構。它不需要等待響應,從而將兩個或多個服務的執行分開。非同步通信的實現有幾種方式,通過RPC(例如,grpc)或通過中介消息匯流排直接調用遠程服務就是一些例子。編排消息傳遞和事件編排都使用消息匯流排通道。 中央消息匯流排的一個優點是一致的通信和消息傳遞語義。這給服務間的直接非同步通信帶來了巨大的便利。我們通常使用像消息匯流排這樣的媒介來保證跨服務通信的一致性。下面將基於使用中央消息管道的假設來討論的非同步通信的種類。
變體
非同步通信可以更好地處理流量激增。體系結構中的每個服務都會生成消息,消費消息或執行兩者。我們來看看這種範式的不同變體。
非同步事件協同
在這種方法中,每個組件監聽中央消息匯流排並等待事件,事件的到來是執行的信號,執行所需的任何上下文都是事件有效負載的一部分,觸發下游事件是每個服務所擁有的責任。基於事件的體系結構的目標之一是將組件分離,不幸的是,需要在設計層面滿足這種需求。
通知組件接受到事件時可能電子郵件或SMS發送。由於所有其他服務需要做的事情是生產事件,因此它看起來可能是彼此分離的。但是,確實需要有組件承擔決定通知類型和內容的責任,通知可以根據傳入的事件信息做出該決定,如果發生這種情況,我們就已經建立了通知和上游服務之間的耦合。如果上游服務將此作為有效負載的一部分,則他們仍然感覺到下游的流量。 即便如此,事件協同也非常適合需要發生的隱式操作。比如錯誤處理,通知,搜索索引等。 這種體系結構遵循分散的工作流程管理。該體系結構適合寫入繁重的系統。缺點是同步讀取需要協調,並且工作流會在系統進行廣播。
編排、非同步和順序
我們可以從我們的協調同步通信方法中借鑒一些。我們可以通過中央編排器建立非同步通信。 每項服務都是中央消息匯流排的生產者和消費者。編排器的職責是將消息路由到他們相應的服務。每個組件消費一個傳入事件或消息,並在消息隊列上生成響應。編排器消耗此響應並進行轉換,然後再前進到下一步。該循環繼續,直到指定的工作流程達到系統中的最後一個狀態。 在這種風格下,工作流管理對於編排器來說是本地的。這種系統在處理寫入流量很大時有很好的表現,同步消費者需要調解。這在所有非同步通信變體中都很流行。 在編排系統中,協同耦合問題的解決方案更加優雅。在這種情況下,工作流工作在編排器上,豐富的工作流規範可以捕獲通知類型和內容模板等信息,對工作流程的任何更改都保留在編排器服務中。
編排和事件協同混合使用
另一個成功的變體是具有編排和事件協同的混合系統。編排非常適合顯示的工作流執行,而協同可以處理隱式執行。在工作流程中執行葉節點可能是隱含的,工作流規範可以促進在特定步驟中發生事件,這可能會導致執行任務,如通知,索引等等,編排可以繼續推動顯式執行。 這兩種方法的融合提供了近乎完美的方案,雖然仍需要採取預防措施以確保它們不會責任重疊,並且明確邊界以決定它們的功能。
概述
非同步風格的體系結構解決了同步體系結構系統所具有的一些缺陷。非同步結構在處理突發大量請求時表現更好。中央隊列允許服務趕上合理的請求積壓,當很多請求在短時間內出現或者服務暫時關閉時,這是非常有用的。 每個服務都以消費者或生產者的身份連接到消息隊列,只有消息隊列需要服務發現。因此,對中央服務發現解決方案的需求不那麼緊迫。此外,由於服務的多個實例連接到隊列,因此不需要外部負載平衡,這可以防止負載平衡器引入導致的隔離級別提升。它還使服務能夠無縫線擴展。
權衡
本質上是非同步的服務流可能很難通過系統進行跟蹤。採用非同步通信的系統會有一些折衷,我們來看看其中的一些權衡點。
更高的系統複雜性
非同步系統往往比同步系統複雜得多。然而,系統的複雜性和性能以及規模的要求是合理的開銷。一旦採用協調器和單個組件,就需要接受非同步執行。
讀取/查詢需要中介
除非專門處理,否則同步消費者受非同步體系結構的影響最大。要麼消費者適應非同步系統的工作,要麼系統為消費者提供同步介面。 非同步架構非常適合寫入繁重的系統。但是,它需要協調讀取/查詢同步,有幾種方法來管理這種需求,每種都有一定的複雜性。
同步包裝
所有方法中最簡單的是在非同步系統上構建同步包裝。這是一個可以調用下游非同步流程的入口點。同時,它保存等待的請求,直到響應返回或發生超時。同步包裝是一個有狀態的組件。傳入的請求將自己綁定到它所在的伺服器上。來自下游服務的響應需要到達原始請求正在等待的伺服器。這對分散式系統來說並不理想,尤其是那種大規模運行的系統。但是,編寫起來很簡單,而且易於管理。這種方法符合具有合理的縮放和性能需求的系統的需求。在進行更為劇烈的重構之前,可以考慮同步封裝。
CQRS
CQRS是一種將讀取與寫入分離的架構風格。CQRS給系統帶來了大量的風險和複雜性,它非常適合大規模運行並需要大量讀取和寫入的系統。在CQRS體系結構中,數據從寫資料庫流向讀資料庫,查詢在讀取優化的資料庫上運行,讀/寫層是分開的,系統保持最終一致性。兩個層的優化是獨立的。這樣的系統結構更複雜,但可以具有更大的規模。而且,組件可以保持無狀態(與同步包裝不同)。
雙重支持
在同步包裝器和CQRS實現之間有一個中間地帶,每個服務/組件都可以支持同步查詢和非同步寫入,這適用於中等規模運行的系統。所以讀取查詢可以在組件之間跳轉以完成同步讀取。另一方面,寫入系統將流入非同步通道。這裡有一個權衡,對系統的讀和寫進行獨立優化是不可能的,或者,這對於在高流量下運行的系統是有益的。
消息匯流排是故障的中心點
這不是一種折衷,而是一種預防措施。在非同步通信方式中,消息匯流排是系統的支柱,所有的服務都不斷地從消息匯流排上生產和消費。這使得消息匯流排成為系統的致命弱點, 因為它仍然是故障的中心點。消息匯流排支持橫向擴展非常重要,否則它可能違背分散式系統的目標。
最終一致性
非同步系統可以是最終一致性,這意味著查詢結果可能不是最新的,即使系統已經發布了寫入。雖然這種權衡可以讓系統更好地擴展,但也需要同時考慮系統設計和用戶體驗。
混合
可以同時使用非同步和同步通信,但這兩種方法的權衡會壓倒他們的優勢。一方面,系統必須交換處理兩種通信風格,同步調用會導致級聯降級和失敗。另一方面,非同步通信會增加設計的複雜性。根據我的經驗,選擇單一方式對於系統設計來說更加富有成效。
結語
馬丁福勒有一個關於如何構建微服務的偉大博客。一旦決定構建微服務架構,需要仔細審議其執行流程風格。對於寫入繁重系統來說,帶有同步包裝的非同步系統是最佳選擇。而對於讀取繁重系統,同步通信就很好。 對於讀寫繁重,但具有適度規模要求的系統而言,同步設計將大大簡化設計。如果一個系統具有顯著的規模和性能需求,那麼使用CQRS模式的非同步設計是一種可選方案。
騰訊雲分散式微服務
騰訊分散式微服務TSF圍繞應用和微服務的PaaS平台,提供服務全生命周期管理能力和數據化運營支持,提供多維度應用、服務、機器的監控數據,助力服務性能優化;擁抱 Spring Cloud 開源社區技術更新和K8s容器化部署。
詳見 https://cloud.tencent.com/product/tsf
問答
微服務架構:跨服務數據共享如何實現?相關閱讀 基於微服務的 Abixen 平台中的領域驅動設計方法次世代的會話管理項目 Spring Session
使用Akka HTTP構建微服務:CDC方法
此文已由作者授權騰訊雲+社區發布,原文鏈接:https://cloud.tencent.com/developer/article/1152802?fromSource=waitui
歡迎大家前往騰訊雲+社區或關注云加社區微信公眾號(QcloudCommunity),第一時間獲取更多海量技術實踐乾貨哦~
推薦閱讀:
※輸入過的WIFI密碼忘了怎麼辦?簡單幫你找回!
※16個合法練習黑客技術的網站
※ServiceDesk Plus配置郵件自動轉換為服務類工單
※1-10 轉CS的優勢之一:前置條件少
※C++性能榨汁機之驚群問題