REST真的完全適合微服務架構嗎?

2021-09-23 00:19:50 字數 3579 閱讀 3862

本文講的是rest真的完全適合微服務架構嗎

【編者的話】作者根據自己的微服務經驗,提出rest並不是微服務的唯一通訊機制,從而介紹了微服務的幾種通訊機制,包括rest、管道以及基於非同步訊息傳遞。同時,作者提出了在不同的場景下可以使用不同的通訊機制。

在我接觸微服務的這段時間,大部分關於如何安裝部署微服務的線上樣例或文章都一致認為rest是微服務之間通訊的唯一方式。因此,你可能理所當然地認為rest就是微服務的一種標準,並且是設計與實現微服務系統一種方式。然而,並非如此。

基於rest的微服務示例比較受歡迎的原因可能是由於它們比較簡易,無需借助任何額外的基礎設施,服務之間通過http協議就可以直接進行同步通訊。

舉個例子來說,假設乙個系統當熱銷**時就需要通知顧客。這個系統可以通過rest微服務實現,如下圖所示:

乙個外部實體傳送乙個存貨清單更新請求到rest閘道器位址。

閘道器將請求**給存貨清單管理服務。

存貨清單管理服務基於它接收到的請求更新存貨清單,隨後傳送請求到熱銷**通知服務。

接著,熱銷**通知服務傳送請求到訂閱管理服務,要求當商品有庫存時所有註冊使用者都需要被通知。

然後,訂閱管理服務傳送郵件rest請求到郵件服務,通過郵件來通知所有使用者。

最後,每個服務依次相應,迴圈回到閘道器並且到達客戶端。

值得注意的是,雖然通訊過程是點對點的,但是固定編碼服務位址是一種非常糟糕的設計選擇,而且這是與微服務基本原則相悖的。取而代之,可以使用服務發現機制,例如

eureka

和consul

,這些機制讓各服務將它們的api註冊到**伺服器,然後客戶端訪問**伺服器的特定api位址。

進行更深入的分析,在實現過程中還需要考慮一些基本事情和缺陷。

根據rest的同步原則,更新庫存的操作直到通知服務完成通知所有相關顧客的任務前都不會進行返回。設想下,如果有件非常出名的商品,顧客希望當有額外庫存時能在1000秒內收到通知,這種同步過程將造成多大影響。效能存在被嚴重影響的風險並且系統的伸縮性也將受到阻礙。

當乙個產品到貨,客戶應當被通知』的認識被根深蒂固的認為應當由清單管理服務來做,但是我不這樣認為。該服務的單一職責就是更新系統存貨清單(存貨清單聚合根)。實際上,它甚至都不需要知道通知服務的存在。在這個模型中,這兩個服務是的耦合度太緊。

服務是會失敗的,當遇到這些情況時,基於微服務的系統需要盡力繼續進行這些功能。由於系統的緊耦合,存貨清單管理服務(舉例說明)就需要乙個失敗策略來處理當熱銷**通知器失效的場景。是應該讓存貨清單更新失敗還是應該讓服務進行重試?至關重要的應該是讓到達通知器的請求盡快失敗,像

hystrix

這種環路破壞模式就能夠做到這點。雖然不論使用何種通訊方式,失敗的場景都需要進行處理,但是將所有的邏輯都繫結到呼叫服務上是非常臃腫的。回到單一職責的問題,我的觀點還是認為存貨清單管理服務不應該負責處理當通知器失效的情況。

克服服務之間耦合度的一種方式就是根據管道企業模式,將路由職責從微服務中剝離。我們的子系統模式如下圖所示:

服務之間的通訊依然基於rest,但不再是『點對點』模式,而是通過官道實體負責編排資料流,不再是通過服務自身。當克服耦合度問題(通過非同步管道,阻塞一部分工作)時,在微服務社群中,這種方式也被認為是一種很好的實踐用以盡可能地保持服務自治性和一致性。使用這種方式,服務必須依賴第三方實體(例如管道編排服務)以便作為乙個系統進行運作,因此,在這種方式下服務是不能夠自給自足的。

舉個例子來說,我們可以注意到管道只會從熱銷**通知器收到乙個單一相應(即使有兩個訂閱者),所以它必須被配置為能夠解析相應,從而讓郵件通知器能夠給每個訂閱者單獨傳送郵件。有人會說,可以將郵件傳送器修改為能夠通過乙個請求批量傳送郵件給不同的訂閱者,如果是這樣,每個使用者的使用者名稱就需要包含在郵件內容中,也就還需要一些令牌替換功能。這就帶來了額外的行為耦合,即通知器需要特別了解郵件傳送器的行為。

在乙個基於訊息傳遞的系統中,服務的輸入和輸出都被定義為指令或者事件。每個服務訂閱那些它們樂於消費的事件,然後通過訊息佇列或者**這類機制可靠地獲取這些事件,當這些事件被其他服務放入佇列中時。

根據這種方式,庫存通知子系統可以被重構,如下所示:

通過共享佇列名和一種一致且眾所周知的指令或事件格式來獲取關聯性,由一種服務引發的事件或者指令需要能夠被其他訂閱者服務所消費。在這個架構中,能夠獲得極大的靈活性、服務隔離性以及自治性。

存貨清單管理例項具有單一職責,即更新存貨清單,不需要關係當完成自身任務時會引發任何其他服務。因此,其他服務能夠被加入系統,它們可以直接消費存貨清單更新事件而不需要修改存貨清單管理服務,或者任何管道編排服務。

同樣,它不需要關心(或者了解)熱銷**通知器是否遭遇事故停止服務,存貨清單依然能夠被順利更新,就像存貨清單管理服務所關心的那樣。存貨清單管理服務對於失敗的無感實際上是一件好事,我們仍然需要一種策略來處理熱銷**通知器的失敗場景,但是像我之前所陳述,這件事情就不是存貨清單管理服務所要負責的。

想要具備能力用以處理像新增、刪除、修改這些改變而不影響其他服務的操作或**,以及能夠優雅地處理諸如服務失敗這類壓力,需要在設計基於微服務系統時考慮兩件非常重要的事情。

然而,世界上所有的非同步訊息傳遞都不是完全美好的,還需要考慮一些缺陷:

和同步程式設計模型比較起來非同步程式設計模型通常更加複雜,這使得非同步程式設計模型設計和實現起來更加複雜。這是因為有許多可能必須克服額外的問題,如訊息排序,重複訊息和訊息冪等性。

此外,訊息**的配置也許要進行考慮。例如,對於同一種服務有多個例項,應該將訊息傳遞給所有服務例項還是只傳遞給其中乙個?這兩種場景都有使用案例。

乙個動作結果未立即返回同樣會增加系統和使用者介面的複雜性,並且在某些場景下,這對於使用非同步方式進行運作的系統子集來說甚至沒有任何邏輯意義。就熱銷**通知器與訂閱管理服務的關係來說,沒有關於需要被通知的訂閱者的相關資訊,通知器就不能正常運作,因此對於這種情況同步rest呼叫就能起作用。這和郵件傳送任務是不同的,因為對於郵件來說沒有必要立即傳送。

由於基於訊息傳遞微服務的分散與自治性,在系統內很難獲得乙個完全清晰的訊息流圖。這使除錯變得更加困難,而且相對於管道方式,系統的業務邏輯更加難以管理。

注意:基於事件的訊息傳遞可以通過應用事件源和cqrs模式進一步擴充套件,但是這超出了本文的討論範圍。可以檢視鏈結獲取更多資訊。
因此在設計你的微服務時哪一種通訊方式更加合適?這與軟體開發(和週期?)的大多數事情是一樣的,取決於具體的需求!如果乙個微服務實際需要同步響應,或者如果它自身需要接手同步響應,那麼rest也許就是你所需要的方式。如果乙個企業要求系統的訊息流能夠被容易地監控和審計,或者考慮到能夠在乙個中心位置修改和檢視訊息流,那麼可以考慮管道方式。然而,基於非同步訊息傳遞系統松耦合與高伸縮的性質能夠很好地適應微服務的的整體思想。通常情況下,儘管設計與實現上存在一些重大的障礙,但是當你決定在基於微服務的系統中使用一種預設的通訊機制,基於事件的訊息傳遞方式是乙個不錯的選擇。

* netflix oss

- eureka和hystrix的主頁

* consul

* antifragile software

- 作者為russ miles

* event sourcing

- 作者為martin fowler

* building and deploying microservices with event sourcing, cqrs and docker

- 作者為chris richardson

原文發布時間為:2016-01-10

微服務與微服務架構

微服務 微服務強調的是服務的大小,它關注的是某乙個點,是具體解決某乙個問題 提供落地對應服務的乙個服務應用,狹意的看,可以看作eclipse裡面的乙個個微服務工程 或者module。例如 訂單服務 支付服務 微服務架構 馬丁.福勒 martin fowler 微服務架構介紹 微服務架構是 種架構模式...

微服務架構

一 先了解一下什麼是單體應用 就是乙個應用程式包含了所有模組功能,各模組同時部署。當然這種應用模式比較容易部署 測試,但隨著專案的加大,單體模式就會變得越來越臃腫,維護的成本逐漸變高。當乙個模組出錯,整個應用都會出現問題,擴充套件能力也會受到限制。二 什麼是微服務 是將整個應用程式分解為多個模組,各...

微服務架構

簡單來說,微服務架構風格想要開發一種由多個小服務組成的應用,每個服務執行於獨立的程序,並且採用輕量級互動,多數情況下乙個http的資源api,這些服務具備獨立業務能力並可以通過自動化部署方式獨立部署,這種風格使最小化集中管理,從而可以使用多種不同的程式語言喝資料儲存技術 james lewis 和 ...