2010-02-17 37 views
6

我發現自己負責繼續開發一個我原本沒有設計的系統,並且不能要求原始設計師爲什麼採取某些設計決策,因爲他們不在這裏。我是一名設計問題的初級開發人員,因此在開始執行我的第一個SOA/WCF項目的項目時,並不知道該問什麼。SOA和WCF設計問題:這是一個不尋常的系統設計嗎?

該系統有7個WCF服務,將增長到9個,每個自我託管在一個單獨的控制檯應用程序/ Windows服務。所有這些都是單實例和單線程的。所有服務都具有相同的OperationContract:它們公開Register()和Send()方法。當客戶端服務想要連接到另一個服務時,他們首先調用Register(),然後如果成功,他們會執行全部與Send()的其餘通信。我們有一個DataContract,它具有一個枚舉MessageType和一個可以包含其他DataContract「有效內容」的Content propety。這個服務對消息的處理是由枚舉MessageType決定的......一切都是通過Send()方法來實現的,然後被路由到一個switch語句......我懷疑這是不尋常的

Register()和Send( )實際上是OneWay和Async ...服務的所有結果都通過WCF CallbackContract返回給客戶端服務。我相信使用CallbackContracts的共同點是促進我們正在使用的發佈 - 訂閱模型。問題不在於我們所有的溝通都適合發佈 - 訂閱,而使用CallbackContracts意味着我們必須在返回的結果消息中包含源細節,以便客戶端可以計算出返回的結果最初是用於什麼......再次,客戶端有一個switch語句可以制定出來如何處理基於MessageType的服務(以及其他嵌入的詳細信息)。

就拓撲而言:服務在圖形中形成「節點」。每個服務都有一個硬件編碼列表,當它啓動時它必須連接到其他服務列表,並且不允許客戶端服務「註冊」它,直到完成所有需要的連接。作爲一個例子,我們有一個LoggingService和一個DataAccessService。 DataAccessSevice是LoggingService的客戶端,因此DataAccess服務將在啓動時嘗試向LoggingService註冊。直到它可以成功註冊DataAccess服務將不允許任何客戶端註冊它。結果是,當整個系統啓動時,服務以級聯的方式啓動。我不認爲這是一個問題,但這是不尋常的?

爲了使事情更復雜,其中一個系統要求是服務或「節點」不需要直接相互註冊,以便將消息發送給另一個,但可以通過間接鏈接進行通信。例如,假設我們有3個服務A,B和C連接在一個鏈中,A可以通過 B ...使用2個跳來發送消息給C

我的確負責編寫路由系統,這非常有趣,但是在我問到爲什麼真的需要它之前,我已經離開了領導層。據我所知,服務不能直接連接到他們需要的其他服務是沒有道理的。除此之外,我還需要編寫一個可靠性系統,因爲要求在系統中具有可靠的消息節點,通過簡單的點對點鏈接WCF可靠地完成這項工作。

在此項目之前,我只在winforms桌面應用上工作了3年,不知道更好。我的懷疑是這個項目過於複雜的事情:我想總結一下,我的問題是:

1)這種思想的圖形拓撲消息跳過間接鏈接異常?爲什麼不直接將服務直接連接到他們需要訪問的服務(實際上我們是這樣做的......我不認爲我們有任何消息跳躍)?

2)在OperationContract中只公開了2個方法,並使用MessageType枚舉來確定消息的用途/用它做些什麼異常?不應該有一個WCF服務暴露了許多具有特定目的的方法,而客戶端選擇了它想調用的方法?

3)正在通過CallbackContracts與客戶進行所有通信。當然,同步或異步請求響應更簡單。

4)服務是否允許客戶端服務連接到它(註冊),直到它連接到它的所有服務(它是客戶端)爲止的聲音設計?我認爲這是我同意的唯一設計方面,我的意思是DataAccessService在與日誌服務連接之前不應該接受客戶端。

我有太多的WCF問題,以後會有更多的問題。提前致謝。

回答

6

那麼,整個事情似乎有點奇怪,同意。

所有這些都是單實例,並且單線程爲 。

這絕對會回來,並導致巨大的性能頭痛 - 保證。我不明白爲什麼有人希望編寫一個單獨的WCF服務(除了幾個邊緣情況,它的確有意義),並且如果你有一個單獨的WCF服務,爲了獲得任何體面的性能,必須是多線程的(這是棘手的編程問題,也是我幾乎總是提出反對的原因)。

所有服務具有相同的 OperationContract的:他們暴露 註冊()和send()方法。

這也很奇怪。所以任何人都會先調用.Register(),然後用不同的參數調用.Send()幾次?有趣的設計,真的...... SOA的假設是你設計你的服務是你想要向外界展示的一組功能的模型,例如,你的CustomerService可能有像GetCustomerByID,GetAllCustomersByCountry等方法 - 取決於你需要什麼。

只有一個帶參數的Send()方法可以定義正在做什麼,看起來有點......不常見,並且不太直觀/清晰。

這是一個圖形拓撲結構的想法, 消息跳過間接鏈接 異常嗎?

不一定。只向外界公開一個接口是有意義的,然後使用一些內部後端服務來完成實際的工作。 .NET 4實際上會引入一個RoutingService in WCF,這使得這些場景更加容易。我不認爲這是一個很大的禁忌。

正在通過CallbackContracts異常地將所有通信回傳給 客戶端。

是的,不尋常的,脆弱的,凌亂的 - 如果你能做到沒有它 - 去爲它。如果您主要是通過簡單的方式撥打電話,如GetCustomerByID - 使這些爲標準的請求/響應呼叫 - 客戶端請求(通過提供客戶ID)並獲取返回值作爲返回值。簡單得多!

如果您確實有長時間運行的服務調用,那可能需要幾分鐘或更長時間才能完成 - 那麼您可能會考慮將請求存入隊列的單向調用,並且稍後會處理該請求。通常,在這裏,您可以將答案存入客戶端隨後檢查的響應隊列中,或者您可以有兩種額外的服務方法給您請求的狀態(是否已完成?),第二種方法是檢索該請求的結果。

希望能幫助你開始!

+0

Send()方法接受一個ActionMessage DataContract,它具有用於路由到目標的字符串Destination字段,以及對另一個DataContract類型的引用作爲有效內容。有效載荷DataContracts全部從具有MessageContentType枚舉字段的基本類型繼承,正是這種服務用於確定它們是否對通過它們的數據處理感興趣,然後纔將它們路由到該消息。目標字符串可以指定您希望消息通過的服務節點類型。 感謝您的信息。在其他一些答覆之後,我將其標記爲答案。 – MrLane 2010-02-17 06:52:02

+0

我應該補充一點,我們確實有一個SessionManagerService,它是我們的Silverlight客戶端系統的「網關」。最初他們確實通過這個網關(使用它的Send()方法)向後端服務發送消息,該消息將消息路由到正確的後端服務,並將消息路由回到來自這些服務的正確瀏覽器客戶端實例。然而,現在,情況並非如此,在客戶端<> SessionManager <> BackEndServices之間使用了單獨的消息,因此eveything是單跳。 SessionManager實際上保留了UI狀態並將其「推送」給Silverlight客戶端。 – MrLane 2010-02-17 07:08:16

5

所有服務都具有相同的OperationContract:它們公開Register()和Send()方法。

您的設計在某些部分顯得不尋常,特別是只暴露了兩個操作。我沒有使用過WCF,我們使用Java。但基於我的理解,Web服務的全部目的是揭露您的合作伙伴可以使用的操作。
只有兩個操作看起來像奇怪的設計給我。您通常使用WSDL公開您的API。在這種情況下,除非您有大量文檔,否則WSDL不會爲合作伙伴增加任何價值。通常操作名稱應該是不言自明的。現在,如果沒有內部知識,您的系統不能被合作伙伴使用。

正在通過CallbackContracts與客戶端進行所有通信。當然,同步或異步請求響應更簡單。

同意你的意見。異步只能用於長時間運行的進程。異步增加了相關性的開銷。