.NET Remoting Use Cases and Best Practices [翻譯]

.NET Remoting Use Cases and Best Practices

 

Written by Ingo Rammer

Translated by Allen Lee

 

      大多數沒有直接接觸過我的人會假設我認爲 .NET Remoting 比其它分佈式應用程序的開發方法更有價值。他們也會假設我把 Remoting 當作任何分佈式應用程序的萬能解決方案。

      他們錯了。事實上,我會爲給定的任務選擇合適的工具。除了 .NET Remoting ,你可以找到許多不同的技術開發分佈式應用程序,而它們每個都有特定的用途:Enterprise Services 和 COM+ 、直接的 TCP/IP 套接字連接、UDP 數據報(UDP datagram)、MSMQ 消息、經由 http 的 Web Service 、經由可靠基礎設施的 SOAP 消息、SQL XML 以及其它更多的。

      在本文裏,我將會討論 .NET Remoting 的各種使用環境、.NET Remoting 裏一些你應該儘可能避免使用的特性,以及一些不會用到 .NET Remoting 的應用情景。討論這些的最終目的是爲了開發出穩定的、可靠的和可擴展的分佈式應用程序。

      首先讓我們看看可以應用 .NET Remoting 的幾個不同環境。Remoting 可以用在你希望你的方法調用 …

  • ... 跨越 AppDomain 邊界
  • ... 跨越本地機器上的進程邊界
  • ... 跨越 LAN 上的機器邊界
  • ... 跨越 WAN 上(仍然在同一個環境裏)的機器邊界

      接着,我們來看看 Remoting 提供的各種不同的特性:

  • SingleCall 服務器端激活的對象(SingleCall SAO)
  • Singleton 服務器端激活的對象(Singleton SAO)
  • 客戶段激活的對象
  • 服務器端主辦方(sponsor)
  • 客戶端主辦方
  • 事件和回調
  • TCP 信道
  • HTTP 信道
  • 自定義宿主(host)
  • IIS 宿主

      寫這篇文章的主要原因是並不是所有特性都適用於所有應用程序環境的。在做深入解釋之前,先來看一張特性/情景矩陣圖以及使用對應的組合是否合適:

  SingleCall Singleton CAO Sponsors@Server Sponsors@Client Events TCP HTTP CustomHost IIS
AppDomain X X X X X X     X  
Process/Local X X X X X X X X X  
Process/LAN X + * *       X   X
Process/WAN X + * *       X   X

      X:完全沒問題
      +:由於有可能保存跨方法的狀態而對擴展性有所影響。如果小心地設計和開發,那麼將不會出問題。
      *:對擴展性造成負面影響。如果你想擴展到多臺服務器上,那麼就不要使用了。
      空白:不推薦。

      但是,你不可能就拿這張矩陣圖而不需要任何進一步的解釋,對吧?那麼,讓我談談這些不同的情景以及我是基於什麼理由來提出這個結論的。

 

跨越 AppDomain 的 Remoting

      你一在 .NET 裏創建一個新的應用程序域,這兩個 AppDomain 就會在後臺使用 Remoting 相互通訊。這樣的話,Remoting 會爲你設置所有的信道和接收器(sink),實際上,它會選用一個最優的格式化處理程序(formatting process)和一個內存(in-memory)信道。

      這裏蘊含這兩層不同的含義: 1 、你不能更換格式化程序或者信道接收器鏈; 2 、你無需太過在意它。它就是能工作的。你也可以使用 .NET Remoting 的所有特性而不產生任何問題。事實上,跨越 AppDomain 的調用是其中一個主要的 .NET Remoting 用例。由於它們很好地集成到框架裏,因此你通常不會發覺你在使用 Remoting 。

安全的特性

  • 所有

 

在同一臺機器上跨越進程

      假設你有兩個運行在同一臺機器上的 Windows Forms 應用程序,你想讓它們能夠相互通訊。或者假設你有一個和你的 GUI 應用程序交換數據的 Windows 服務。 你可以使用哪種協議? Remoting !

      這是 TcpChannel 派上用場的其中一個事例,因爲它允許你在構建它的時候通過指定 rejectRemoteRequests = “true” 來限制所有進來的連接必須是來自你自己的機器的。在這種情況下不必過多考慮安全問題。(然而,如果你在 WinForm 之間的通訊使用固定端口號,那麼當你的應用程序運行在 Windows Terminal Services 上並且在同一時間裏有兩個或者更多的用戶試圖使用時將會出問題。)

      我還要告訴你一個關於 .NET Remoting 的特性的好消息,所有特性在同一臺機器上的客戶端和服務器端上都能正常工作。

安全的特性

  • 所有

 

在 LAN 裏的多臺機器上跨越進程

      好吧,現在我們來看一下現實中的情況。這是你通常的分佈式 LAN 應用程序。這種應用程序還可以分爲兩個不同的類別:

  • 單一服務器(single-server)應用程序
  • 可擴展應用程序

不要使用事件和回調

      無論你的應用程序屬於哪個類別,我強烈建議不要再網絡應用程序裏使用事件、回調或者客戶端主辦方。是的,使用它們是可以的。是的,在應用某個工作區(workaround)後它們可能會工作。真正的問題在於它們不太穩定,而且性能也不如預期那樣好。導致這個穩定性 / 性能缺點的是調用模型。首先,你必須從服務器的角度考慮以同步還是異步的方式調用事件。對於第一種情況,服務器必須等待所有客戶端迴應和處理回調,這極大地增加了請求時間。然而,如果你決定以異步方式使用它們,你可能會遇到許多不同的問題,輕則線程池出現線程短缺,重則事件丟失和應用程序鎖定。

      但是,如果你希望收到客戶端的通知呢?在這種情況下,我會根據可靠性需要考慮 UDP 或者消息隊列。使用 MSMQ 允許服務器端應用程序向監聽的客戶端發送消息而無需等候接收回應(或者等候客戶端完成處理)。 這樣就可以更好地處理請求的週轉了。

你認爲客戶端激活對象怎麼樣?

      那麼爲什麼我也把客戶端激活的對象包含到在這個環境裏不推薦使用的特性列表裏呢?理由是 CAO 總是和激活它們的機器綁定在一起的。這意味着你不能爲這些對象使用負載平衡(load balancing)或者故障轉移羣集(failover clustering)。另一方面,如果你使用 SingleCall SAO,你就可以很容易地使用 Windows Network Load Balancing (NLB)把方法的調用隨機地分派給多個可用服務器中的一個。

      如果你運行的是一個單一服務器應用程序,那麼這對你來說沒什麼所謂。但是,如果應用程序有可能用到服務器端羣集上,那麼 CAO 將毫無疑問限制了它的可擴展性。

      但是,你不應該僅僅考慮可擴展性:CAO 同樣會對單一服務器的情況造成影響。當運行 SingleCall SAO (以及在數據庫裏精確地保存所有狀態信息)時,你可以在需要時關閉和重啓你的服務器。例如,你可以升級到新的版本或者應用一些補丁(bug fix)而用戶無需關閉並重啓你的客戶端應用程序。然而,你一使用 CAO 就會馬上失去這個特性。如果你重啓了承載 CAO 的服務器,客戶端應用程序將會在調用這些對象的任何方法時接收到異常。 CAO 不會在你重啓服務器之後恢復。如果你想獲得透明的可重啓性(restartability)和最大的可擴展性,請不要使用它們。

最佳的信道 / 格式化程序搭配是哪組?

      對於任何跨越多個宿主的應用程序,我推薦使用 HttpChannel 和二進制格式化程序。理由很簡單:你可以在標準的 Visual Studio .NET 項目裏開發和調試你的應用程序,而在部署時你可以輕易在 IIS 上承載服務器端組件,這樣做有許多好處:內建的驗證機制(基本 HTTP 驗證或者 Windows 集成驗證)、內建的加密機制(SSL)以及可以關閉 HTTP keep-alive 功能,由於這樣能減少對羣集中個別服務器的依賴,因此可以進一步提高應用程序的可擴展性。

安全的特性

  • 承載在 IIS 上並使用 HttpChannelBinaryFormatter 的 SingleCall SAO
  • 就這樣。如果你想安全的話,那麼除此之外不要使用其他特性了。另外還要記住,當你在服務器端的方法返回一個 MarshalByRefObject 時,你實際上創建了一個類似於 CAO 的對象,因此應該避免,如果你希望項目具有可重啓性和最大的可擴展性的話

 

經由 WAN/Internet 跨越進程

      隨着應用程序的發展,你衝出了局域網的邊界,另一些問題也隨之而來。處於第一位的絕對是網絡延遲。你不得不通過粗粒度接口(chunky interface)減少跨網絡調用的次數。在粗粒度接口裏,你會在網絡上的一次往返中傳輸儘可能多的(並且儘可能都是必須的)數據。例如,如果客戶端應用程序處理客戶對象和地址,那麼當客戶端應用程序請求某個客戶的信息時,你一定會傳遞這個用戶的所有已知地址。一個可選的做法是使用兩個不同的方法 GetCustomer()GetAddresses() ,但這樣會使網絡的週轉次數加倍,因而極大地減少了應用程序的響應次數。

      然而,你應該注意在這裏取得一個平衡。同時傳輸客戶的全部訂單信息或者完整的聯繫歷史可能不是最佳的做法,如果在 99% 的情況下你不需要那些數據的話。這確實是一個平衡的問題。

      我想,對於這樣的應用程序,我可以提供的最重要的建議是在低帶寬、高延遲的網絡環境中進行開發。不要在通過 LAN 連接的多臺機器上運行服務器端和客戶端。相反,使用簡單的舊式調制解調器把客戶端連接到 Internet 。這樣做可以讓你在開發期間發現並體驗存在性能問題的地方——沒有比用戶響你的電話並且告訴你應用程序慢得很更令人感到難爲情了。

      關於 Remoting 的特性的使用,我能給你的建議基本上和 LAN 環境下的一樣:使用承載在 IIS 上並使用 HttpChannelBinaryFormatter 的 SingleCall SAO。另外,你還應該保證絕對不會使用事件、回調或者客戶端主辦方,因爲這些特性在客戶端的計算機和服務器之間存在着防火牆、代理服務器(proxy)或者 NAT 設備時可能無法工作。然而,在 LAN 環境中使用事件可能僅僅導致應用程序不穩定,它們也將妨礙應用程序在 WAN 環境下工作。

安全的特性

  • 承載在 IIS 上並使用 HttpChannelBinaryFormatter 的 SingleCall SAO

 

不使用 Remoting 的情景

      在介紹了 .NET Remoting 的四種不同的應用情景之後,我想說一下在哪些情況下我將不會使用 Remoting。

讓我們使用 SOAP 吧!

      如果你打算使用 SOAP Web Service 整合不同的平臺或者不同的公司,我強烈建議你考慮 ASMX (ASP.NET) Web Service 而不是 Remoting 。這些 Web Service 是基於工業標準的,與 Web Services Enhancements (WSE)等框架結合使用,就能以平臺獨立和麪向消息的方式使用所謂的 GXA 或者 WSA 規範(WS-Security 、WS-Routing 、WS-Policy 、WS-Trust 、WS-SecureConversation 等等)的實現了。

      ASMX Web Service 提供了基本的 Web Service 特性,例如 WSDL-first 的開發、doc/literal 的使用、更爲簡單的 SOAP 標頭(SOAP Header)檢查等等。

      那麼,讓我再重複一次:如果你想要 SOAP ,結合 WSE 使用 ASP.NET Web Service 是你唯一的選擇!

面向服務的體系結構

      當今工業界的一個流行術語是“面向服務的架構體系”(SOA),它在企業環境中提供平臺獨立、面向消息和鬆散耦合的服務。你可能已經猜到了: Remoting 並不是實現這些的正確選擇。這裏也可以考慮使用 ASMX+WSE 。

分佈式事務、細粒度安全需求 ……

      一個完全不同的不適宜使用 Remoting 的情景是當分佈式事務處理(distributed transaction)、細粒度安全需求(fine grained security requirement)、可配置進程隔離(configurable process-isolation)、發佈和訂閱事件等是必須的時候。是的,事實上你可以開發你自己的信道接收器(channel sink)並把它們插入 Remoting 框架以便能夠使用這些特性。但是,你爲什麼要這樣做?爲什麼要浪費時間?在 .NET 中已經存在另一個包含所有這些特性的框架了:Enterprise Services。

      如果你的應用程序可能用到任何下面所提到的服務,那麼你就應該考慮使用 Enterprise Services 而不是 .NET Remoting 了:

  • 非常靈活的、可配置的驗證和授權方式
  • 基於角色的安全機制,它使用與 Windows 用戶帳戶相獨立的角色
  • 對象的實時(just in time)激活
  • 對象池(object pooling)
  • 進程隔離
  • 用作 Windows 服務的服務器端組件
  • 通過 MSMQ 讓組件的交互自動排隊

      另外, Windows Server 2003 上的 COM+1.5 還提供了一種叫做“沒有任何組件的服務”(SWC)的特性。這使得你不必讓組件繼承自 System.EnterpriseServices.ServicedComponent 並在 COM+ 目錄(COM+ catalog)中註冊就可以使用 Enterprise Services 框架的大多數服務了。

 

Remoting 的九個準則

      Remoting 提供許多特性,它們的適用性會隨使用情景的不同而不同。爲了使你的應用程序能有最大的穩定性和擴展性,從而保證它的可靠性,如果你要讓不同的機器相互通訊的話,那麼你就應該遵循下面九個準則:

  • 僅使用以 SingleCall 模式配置的服務器端激活的對象
  • 使用 HttpChannelBinaryFormatter。如果你需要可擴展性、驗證和授權等特性的話,把你的組件承載在 IIS 上。
  • 屏蔽 IIS 的 HTTP keep-alive 功能以便獲得最大的擴展性。
  • 如果你想獲得擴展性的話,請在開發期間在服務器羣集中使用 Windows Network Load Balancing 。保證不與任何客戶端相關聯,並且保證在開發期間屏蔽 HTTP keep-alive 功能!
  • 不要使用客戶端激活的對象,也不要跨越遠程邊界傳遞任何 MarshalByRefObject,如果你打算運行在羣集上的話。你可以輕易地捕獲這種情況,如果你使用 .NET Framework 1.1 版的話,因爲它會在這種情況中拋出 SecurityException 或者 SerializationException。(是的,你可以修改這個設置,但你不應該這樣做!)
  • 不要使用事件、回調合客戶端主辦方。
  • 不要使用靜態字段爲會被用戶修改的操作數據保存狀態信息。相反,總是把這類狀態信息保存在數據庫裏。如果你在內存中保存不穩定的狀態信息,那麼當你試圖把應用程序擴展到服務器羣集上時將會出現問題。僅當信息不會改變時才緩衝它(像一組州名或者城市名),否則你將會潛入在羣集上同步緩衝的惡夢。
  • 不要在從 .NET 到 .NET 以外的任何通訊上使用 Remoting 。在任何與 SOAP 、面向服務的架構體系和平臺獨立相關的情況中使用 ASP.NET Web Service 和 Web Services Enhancements(WSE)。
  • 不要試圖使用自定義信道接收器來實現分佈式事務處理和安全等特性。相反,使用 Enterprise Services ,如果它適用於你的環境的話。 .NET Remoting 不是中間件(middleware),它僅僅是一個傳輸協議,如果你需要服務,那就使用面向服務框架。當然,你也可以使用 .NET Remoting 訪問 Enterprise Services 的組件。

      如果你遵循這些指導原則,那麼你的 Remoting 應用程序將會非常穩定、可靠和可擴展。

 

關於作者

      Ingo Rammer 主要在歐洲中部從事獨立諮詢、開發、寫作和培訓等工作。2002年出版了《Advanced .NET Remoting》《Advanced .NET Remoting in VB.NET》。在他的日常諮詢工作中,他主要關注 .NET 應用程序的架構體系,併爲電信業和軟件業的多家公司服務。你可以通過 http://www.ingorammer.com 與他取得聯繫。

 

關於本文

      前段時間由於需要開始了 .NET Remoting 的研究之旅,中間有幸拜讀 Ingo Rammer 先生的《Advanced .NET Remoting》,跟隨着書中的連接機緣巧合之下找到了本文。拜讀之後,覺得可以把本文的翻譯作爲一個階段性的總結(也可以說是偷懶,哈哈),隨即書信 Ingo Rammer 先生表明意思,在徵得他的同意後便開始了本文的翻譯之旅了。若想查看原本,請點擊這裏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章