0

我正在尋求一個設計問題的答案,我在這個問題上沒有找到任何文獻的答案。請允許我解釋用例,我的解決方案,並徵求您作爲主題專家的意見。在微服務之間共享數據

用例: 我們有幾個微服務,都返回來自不同業務領域的某種形式的內容。我們使用Spring Cloud Netflix,因此網關服務將流量路由到內容服務。這些服務中的一部分(如果不是全部)需要從請求派生的數據,並且是不可變的。一個簡單的例子是語言環境,但也有其他專有信息。

解決方案: 我目前獲得的共享數據的網關服務,並在NoSQL的數據庫具有獨特的鍵作爲持續JSON。然後,我在將請求路由之前將該密鑰添加爲請求標頭。我有一個內容服務在構建時包含的共享庫,它包含一個Spring bean,它從請求頭中讀取密鑰,使用密鑰讀取存儲的數據並初始化它自己。這使得內容服務可以在不知道底層機制的情況下訪問共享數據(通過簡單地注入前面提到的bean)。 如果內容服務調用另一個內容服務,它負責將唯一密鑰添加爲請求標頭。

辯論: 我與同事們的辯論是,爲此目的使用共享數據存儲是否合適。我認爲服務將域特定的數據泄漏給其他服務是不好的,但是所討論的數據並不是域特定的,所以擁有共享數據庫並傳遞密鑰沒有任何問題。另一種方法是通過所有我認爲是多餘的共享數據。

你的想法是什麼?

編輯:我看到有人投來關閉的問題。除非他們能夠指出我討論微服務之間數據共享的參考,否則這種警務是妨礙有意義討論的障礙。並非每個問題都是布爾型的是/否答案,有些則需要更深入的思考。

+3

我想說一個服務應該擁有和管理數據存儲。數據存儲本身不應該共享。 – duffymo

+0

@duffymo數據認證的結果呢?你認爲每個服務應該解析一個JWT令牌來提取相同的信息,或者它應該被完成一次並存儲以備後用?我爲共享數據創建抽象沒有任何問題,這就是我的問題中的Spring bean正在做的事情。 –

+0

我相信VTC與這張貼在StackOverflow上相關。 [Programmers SE]的設計參數[更適合](http://meta.stackexchange.com/questions/124867/where-should-i-ask-software-architecture-design-questions)(http://程序員.stackexchange.com /)。 – Mitch

回答

0

在大多數情況下,複製的成本被方便所抵消,但您始終可以將共享數據視爲其他服務所擁有。

如果只有一個作家的「共享」數據,你訪問它的方式,允許客戶端的獨立版本,那麼你可以作爲一個非傳統的公開的服務查看共享數據。

實施例:

  • 服務A擁有實體A1,存儲在SQL Server作爲表A1
  • 服務B擁有實體B1,這就需要數據從A1實體

在經典服務B將通過對服務A的呼叫訪問A1。

Service B --HTTP--> Service A --SQL--> A1 

Alt事實上,服務A可以創建一個視圖,允許服務B直接訪問A1。

Service B --SQL--> vwA1_version1 --SQL--> A1 

當服務中的變化領域的佈局,服務A更新vwA1_version1允許與老客戶的向後兼容性和新的客戶定義vwA1_version2

+0

請將您的答案改爲特定於我的問題。關於共享數據存儲的一般性討論沒有幫助。 –

+0

@AhhijitSarkar,你沒有問一個具體的問題,你問了一個普通的問題。對於「您可以在SOA中共享數據存儲」這個問題,我的回答就是。如果您希望得到「我應該通過JWT還是用戶ID」的特定答案,我會強烈支持令牌。 AAA已經足夠普遍,大多數服務將不得不訪問數據。驗證簽名比DB調用便宜得多。 – Mitch

2

的第一個答案的激烈辯論後,讓我借一些觀點:

,往往出現是如何處理的,例如身份驗證信息的請求碰到的第一個服務之後,再依次調用一個用例其他服務。現在的問題通常是:我是否交出認證信息(如用戶名和組等),還是隻交出令牌,客戶端發送並讓下一個服務再次查詢認證信息。

據我所知,微服務社區尚未就解決此問題的「慣用」方式達成一致。我認爲這是一個很好的理由,它在各種應用程序中提出了不同的要求。有時候,只有在第一個服務中需要進行身份驗證纔會受到外部請求的影響 - 那麼請不要將太多的工作放在身份驗證中。我認識的大多數系統仍然有更高的要求,因此需要在認證方面進一步的複雜程度。

讓我來看看如何解決這個問題:最簡單的方法是將客戶端在後端服務之間發送的訪問令牌交給他人。是的 - 這種方法要求每次服務在每次遇到請求時都要重新查詢用戶信息。如果(並且我認爲這不會在您的系統中發生這種情況)每個請求有25個跨服務呼叫 - 這很可能意味着在某種認證服務中有25個呼叫。大多數人現在會開始尖叫恐怖的重複 - 但讓我們換個角度來看:如果同一個系統是一個結構良好的龐然大物,你仍然可以在不同的地方進行這些調用(可能每次打一個數據庫)你的過程。微服務體系結構中的這些調用的重大問題是網絡開銷,這是事實 - 如果做錯了,它會殺了你!我會給你我們所採取的解決方案,並在我們的重負載下運行良好:

我們開發了一個令牌服務(我們將很快開放採購)。除了存儲令牌,過期日期和一些無模式JSON內容的組合外,此服務不做任何其他事情。它有一個非常簡單的REST界面,可以讓你創建,無效,擴展和讀取令牌及其內容。該服務具有多個後端,可根據其運行環境進行配置。出於開發目的,它有一個簡單的內存中存儲,不會以任何方式同步,保留或複製。對於生產環境,我們編寫了一個後端,用於在多個實例之間同步這些令牌(包括所有諸如仲裁,異步持久等等)。這個後端使我們能夠很好地擴展這項服務;這是我提出的解決方案的前提:如果每次服務節點在每次收到請求時都必須獲取與令牌相關的信息,則提供它的服務必須非常快!我們的實現返回令牌及其信息的時間遠遠少於5毫秒,我們相信我們可以進一步降低這一指標。

我們的另一個策略是編排對令牌服務產生較重查詢的服務(與僅檢查令牌有效性/存在相比,接收內容比較昂貴),以使它們位於相同的物理節點上或靠近將網絡延遲降至最低。

什麼是更一般的消息:只要數量或這些調用與處理的內容量保持不耦合,就不要害怕跨服務調用(不好的示例here)。被更頻繁地調用的服務需要更加仔細地設計,並且他們的性能需要經過非常優化以具有最後的毫秒。這種系統關鍵服務中的DB-Hits例如是絕對的Nogo,但有些設計模式和體系結構可以幫助您避免它們!

您可能已經檢測到我沒有直接回答您的問題進行辯論。爲什麼?我強烈反對在服務之間共享數據庫。即使這些數據庫是無模式的,您也會將兩個服務結合在一起,而不會顯示這種依賴關係。一旦你決定重新構造一個令牌服務中的數據,並且即使只是閱讀這個數據庫,還有另外一個服務 - 你只是搞砸了兩個服務,你可能會意識到它太遲了,因爲依賴不透明。服務中的狀態/數據只能通過定義良好的接口來訪問,以便可以很好地抽象,開發和獨立測試。在我看來,改變一個服務中的持久化技術或結構不應該搞砸,甚至不需要改變其他服務。通過它的API獨立訪問服務,可以重構,重建甚至完全重寫服務,而不必依賴其他服務。這就是所謂的解耦!

讓我知道這是否有幫助!

+0

你提出了一些我基本同意的觀點。訣竅是如何給貓耳鳴。您可以擁有定義良好的界面的服務,但爲了調用它,您需要輸入參數。 在我的問題中,定義良好的接口是Spring bean(沒有說所有接口都必須是HTTP),它從共享數據庫中提取數據。它需要密鑰才能這樣做,並且使用請求頭將密鑰從服務傳遞到服務。 –