2013-03-31 35 views
5

假設我們有一個SOA基礎結構,如下圖所示,並且每個服務都可以在不同的主機上運行(這對於兩個額外的網絡服務尤其有效)現場「和」支付系統「)。面向服務的體系結構和鬆散耦合與SQL連接

SOA infrastructure

顯然,我們已經得到了一個數據(持久性)層。假設它通過EJB + JPA或類似的東西來實現。

如果我們想加入不同的服務,我看到至少有幾個選擇之間的數據(用戶界面):

    我們想要做的高效
  • 加入以RDBMS的水平,所以我們有一個包(即persistence.package),其中包含全部實體和會話正面(CRUD實現),它們以某種方式必須共享(如何?)爲每個服務部署。也就是說,如果我改變順序模式中的某些東西,我必須重新部署這個包,在幾乎所有東西之間引入緊密耦合。而且數據庫必須是唯一的,共享的。爲了避免這些問題,我們爲每個不同的服務(即order.package)保留一個實體包,並讓服務通過一些協議(soap,rest,esb等)進行通信。所以我們可以在每臺主機上保存本地數據(無共享體系結構),我們不需要重新部署實體包。但是,這種方法是可怕的數據挖掘作爲必須搜索和返回多個服務之間的相關數據將非常低效的(因爲我們不能做SQL連接)

是否有更好的/標準方法查詢到上面指出的問題?

回答

4

SOA的主要動機是可以單獨更換的獨立組件。正如Marco提到的,次要動機是將系統簡化成更容易解決的小問題。 不同業務的好處是靈活性的缺點是更多的管理和開銷 - 即開銷應該由你得到的是什麼是合理的 - 見例如SOA反模式,我發表了一篇名爲Nanoservices其中談到這種平衡

另一件事要記住的是,Web服務API並不自動意味着這是一個服務邊界。屬於較大服務的多個API仍然可以連接到下面的同一個數據庫。例如,如果您的系統中的付款和訂單屬於一起,您不應該因爲它們是不同的API而將它們分開(在許多系統中,這些確實是不同的問題,但是,這又不是自動的)

何時以及如果您確實找到邏輯分離的服務,而不是遵循Marco的建議,並確保服務是孤立的,不共享數據庫。通過這種方式隔離服務可以改變他們的能力。然後,您可以使用composite front end將它們整合到UI中。您應該注意,這適用於應用程序的操作方面,因爲您只需要每個服務的幾個項目。對於報告,您希望像aggregated reporting這樣的東西,即將不可變的數據副本導出到針對報告進行優化的中央數據庫中(例如,非規範化的星型模式等)

+0

「這個[只]適用於應用程序的操作方面,因爲您只需要每個服務的幾個項目」。的確是這樣的問題:通常我們需要來自不同服務的大量數據,UI中的複雜查找和實時搜索。關於彙總報告我很少看到這種數據可以被認爲是不可變的情況(所以通常非規範化引入了同步問題)。 – gpilotino

+0

那麼說阿蒙。我認爲最好的@gpilotino是閱讀關於DDD的一些信息;這是一本非常好的書:http://www.infoq.com/minibooks/domain-driven-design-quickly,並從那裏移動。 – Marco

+0

沒有@gpilotino反規範化不會引入同步問題,不知道你從哪裏得到。使用不同的寫入和讀取模型確實會引入同步問題,但這與數據被非規範化無關。 – Marco

2

哦,我的朋友你只是讓整個場景變得複雜,但這不是你的錯,像MSFT,甲骨文和其他大型企業級軟件供應商這樣的公司喜歡把事情變得更容易,他們這樣做是有原因的:縱向擴展服務意味着更多的許可證。

你可以採取一種不同的方法,暫時忘掉所有那些大詞彙,EJB,JPA等等,就像曾經說過的聰明人一樣,將較大的問題分成較小的部分,這樣就不會產生大問題有一些理論上應該更容易處理的小問題。

因此,您的系統中有幾項服務:人員,支付系統,訂單,產品,ERP ...暫時讓我們認爲這些邊界在商業實體方面是正確的。想象一下,這些服務是你公司的不同實體部門,這意味着他們只關心屬於他們的數據,沒有別的。

然後你可以說,支付部門都有自己的數據庫,同樣適用於訂單,當然他們還需要爲各部門與對方溝通,並且可以輕鬆與系統生成的公共代理鍵。這意味着每個服務都使用內部密鑰維護其所有內部實體的參照完整性,但是如果需要將我提供給其他服務的記錄使用,例如可以使用Guid密鑰,例如,:

enter image description here

的支付服務需要訂單ID和客戶ID,但這些實體屬於自己的服務,所以不是共享每個記錄的私有密鑰(主鍵),每條記錄將有而是服務將使用的主鍵和代理外鍵來共享它們。事情是,你應該致力於建立鬆耦合的服務,每個服務都有自己的「小」數據庫。每個服務還應該有各自的API,不僅應該由前端使用,還應該由其他服務使用。您應該避免的另一件事是使用DTC或其他事務管理提供程序作爲服務範圍的事務擔保人,只需採用不同的體系結構方法即可輕鬆進行歸檔。

不管怎麼說,如果你還沒有關於DDD的話,它會給你一個關於如何構建企業級軟件的不同概述,並且btw EJB遠離它們。

UPDATE:

您可以使用類似事件SOA,但讓我們保持簡單在這裏。已註冊的客戶來到您的網站下訂單。負責此事的服務是訂單。產品的外部ID列表被提交給訂單服務,訂單服務然後註冊訂單,此時訂單處於「等待付款」狀態,此服務返回公共Guid訂單ID。爲了完成訂單,客戶需要爲貨物付款。付款詳細信息會提交給付款服務,該服務會嘗試處理付款,但爲此它需要訂單詳細信息,因爲前端發送的唯一內容是訂單ID,並且要這樣做,它會使用訂單ID中的GetOrderDetails(Guid orderId)訂單的API。付款完成後,Payments服務會調用訂單API PaymentWasCompletedForOrder(Guid orderID)的另一種方法。讓我知道如果有什麼你沒有得到。

+0

好的,但這仍然無法解決「具有相關數據的大連接」問題。當然,我可以將外鍵保留在訂單子系統中,但是當我需要一個與用戶名相關的訂單列表時,這些訂單列表的效率會很低(大小方面要尊重sql連接)以詢問人員子系統等等。忘記ejb和技術,我的問題是,如果我不想同步/傳播模式更改(使事情鬆散耦合),應對這種情況的最有效方式是什麼。 – gpilotino

+0

你可能會說,只保留每個系統中需要的每種報告(數據列表)的額外數據。比方說,在網絡子系統中複製整個訂單列表,以便網站用戶可以查看它們。但是這引出了這個問題:如何保持同步?假設我在訂單子系統中更改訂單狀態,必須將其鏡像到網站中。所以,在非規範化數據的情況下,保持同步會變成一個集成地獄。 – gpilotino

+0

我知道你的意思,但問題是,網絡系統不是一個適當的部門,所以它不應該存在。就像我說的,每個服務都應該有自己的API層。在訂單域中,您有與買方外部ID關聯的訂單列表,然後將其映射到人員服務中的私人ID,因此我不知道問題出在哪裏。 – Marco