我發現自己負責繼續開發一個我原本沒有設計的系統,並且不能要求原始設計師爲什麼採取某些設計決策,因爲他們不在這裏。我是一名設計問題的初級開發人員,因此在開始執行我的第一個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問題,以後會有更多的問題。提前致謝。
Send()方法接受一個ActionMessage DataContract,它具有用於路由到目標的字符串Destination字段,以及對另一個DataContract類型的引用作爲有效內容。有效載荷DataContracts全部從具有MessageContentType枚舉字段的基本類型繼承,正是這種服務用於確定它們是否對通過它們的數據處理感興趣,然後纔將它們路由到該消息。目標字符串可以指定您希望消息通過的服務節點類型。 感謝您的信息。在其他一些答覆之後,我將其標記爲答案。 – MrLane 2010-02-17 06:52:02
我應該補充一點,我們確實有一個SessionManagerService,它是我們的Silverlight客戶端系統的「網關」。最初他們確實通過這個網關(使用它的Send()方法)向後端服務發送消息,該消息將消息路由到正確的後端服務,並將消息路由回到來自這些服務的正確瀏覽器客戶端實例。然而,現在,情況並非如此,在客戶端<> SessionManager <> BackEndServices之間使用了單獨的消息,因此eveything是單跳。 SessionManager實際上保留了UI狀態並將其「推送」給Silverlight客戶端。 – MrLane 2010-02-17 07:08:16