关于.NET Core是否应该支持WCF Hosting的争论
本文要點
本文試圖回答“.NET Core 是否應該支持 Windows 通信基礎(WCF) Hosting?”的問題;
支持者論據:許多工程師喜歡把 WCF 作為一種編程模型,不希望因為遷移到 .NET Core 而產生(機會成本)開銷;
WCF 的優點包括嚴格基于契約的編程模型、靈活的端點和綁定、安全,等等,需要很少的管道代碼;
反對者論據:WCF 和 ASP.NET WebAPI 及 REST 存在潛在的冗余,而且,WCF 經常需要采用非常復雜的方式實現;
創建服務器端 WCF 的投入是不值得的,應該優先考慮類似 SignalR 這樣的工具。
.NET Core 是否應該支持 Windows 通信基礎(WCF) Hosting?在許多人看來,這似乎是一個奇怪的問題;答案很明顯……是?否?好吧,實際上,這個問題的正反雙方都在為自己的立場激烈辯護。本文將分析這場爭論,說明雙方的論據。
爭論變得如此激烈,以致于 WCF for .NET Core 項目成員 Barry Dorrans 不得不在 1 月份暫停了有關這個問題的辯論。我們將分析這場爭論,從支持者的觀點開始。
2016 年,Jan Johansson 發起了一個話題,讓人們列出他們在使用而且希望出現在 .NET Core 中的 WCF 特性。正如下面的匯總表所示,開發人員實際上正在使用 WCF 的許多高級特性。
事務性隊列編程模型
“ 行為(Behaviors)”
“綁定(Bindings)”
“上下文(Context)”
基于契約的編程模型
契約行為
基于契約的編碼模型
“發現(Discovery)”
“持久化服務(Durable services)”
“端點行為(Endpoint Behaviors)”
“可擴展性(Extensibility)”
可擴展模型
“頭(Headers)”
實例管理
攔截模式管道
用于檢測和訪問 SOAP 頭的消息查看器
元數據互換
MEX 端點和 MEX 框架
命名管道
Net.Pipe 綁定
Net.TCP 綁定
NetTcp(半雙工)
“操作行為(Operation Behaviors)”
OperationContext
有序消息
隊列服務
可靠性
安全性
使用 ServiceModel.ServiceHost 的自托管
服務行為
System.Transactions
限流
注意,這些全都是 WS-*或 WCF 特有的特性。例如,當他們說“可靠性”,他們實際上是說 WCF 支持 WS-ReliableMessaging 標準。
WCF 現狀
許多人都有這樣的印象,就是 WCF 僅用于遺留代碼。但實際上,有許多公司在積極投資 WCF 軟件開發。下面是一些例子。
Oliver C. Lanz 寫道:
我舉一個具體的業務案例,就是我們有一個有著幾百萬行代碼的投資管理系統,服務器端目前托管在世界范圍內大約 200 家保險公司和銀行本地的 MS Windows Server 上。我們有大約 100+ 種服務類型,在最大的部署中,有大約 700 到 800 個并發服務實例在運行。我們的產品推動著核心業務的關鍵部分。
我們客戶的 IT 支出非常高。這也是我們希望在未來幾年做出重大改善的地方。其中一部分內容是找到托管環境的替代方案。一個比較好的選擇是 Windows Nano 或 .NET Core on Linux。為了能夠采用 .NET Core(或 Windows Nano),我們將失去 WCF 服務器端。
由于我們非常喜歡把 WCF 作為一種編程模型,我們無意重寫我們的應用程序,除非將來的托管環境不再提供 WCF 服務器端。我們用了許多特殊的特性。要開始采用 .NET Core,下面是一些重要的特性:
[...]
是的,我們會繼續在 .NET Core 上構建 WCF 服務。
Niplar 寫道:
在過去的六年里,在我參與過的方案中(.NET 領域),我們總是基于 WCF 處理方案的服務層(位于防火墻&內部網后面)。沒有東西能像 WCF 那樣為我們提供同樣的靈活性和對不同通信渠道的支持。
因為沒有明確的 WCF 支持,所以我一直在阻止把生產環境遷移到 .NET Core。如果 .NET Core 不支持 WCF 服務器,我們就需要重寫大量的基礎設施代碼;總之,最終是模擬 WCF 編程模型。
我參與過的最大的方案供 300 多家健康醫療機構使用,重寫服務層和功能就是一項巨大的投資,就不用說面臨的高風險了。
事實上,就是在那個方案中,我們曾希望找到一種方式,可以在新產品中統一服務器和嵌入式設備(Linux)的編程模型。在 .NET Core 上支持 WCF 服務(不只是客戶端)會給我們帶來非常大的幫助和成本節省,因為那就不需要兩個開發團隊了;而代之以一個比較大的、非常專注的團隊。
Fernando Ferreira Diniz de Moraes 寫道:
我的情況和[Oliver C. Lanz]的非常相似,只是我的業務場景是銷售網點系統。和他一樣,我們把應用程序部署到世界各地的許多商店中。為了減少基礎設施成本,我們也在尋找托管應用程序的替代方法。就像[Jan Johansson]所說的那樣,隨意部署 WCF 服務就很好,給我們帶來了巨大的靈活性。
WCF 在我們的應用程序中扮演著重要的角色:它基于一個插件架構,其中的插件主要是 WCF 服務,因此,插件之間的通信實際上是 WCF 調用。這方面的改變意味著我們必須重寫/重新構思許多基礎設施代碼。
在我們的情況下,使用 ServiceHost 實例的自托管和基于契約的編程模型至關重要。我們的計劃是,不僅要遷移現有的服務,還要創建新服務。
Websitewill 補充道:
我做過許多利用 WCF 多方面特性的項目。我使用的大部分 WCF 特性(幾乎一切)目前都從 .NET Core 中消失了。許多缺失的功能需要各種第三方庫(或大量的自定義代碼)來填補,當 WCF 已經可以很好地發揮作用時,這個層面的投資是不值得的。最重要的一點是,WCF 極大地提高了我們團隊的生產力。
目前,對我而言,最大的缺失是 WCF 提供的可擴展模型。
我的大部分項目都利用這個功能實現與其他組件(輕量級 WCF 服務)橫切關注點的完全解耦。WCF 提供了一種極好的機制來實現這一點,不需要來自第三方的面向方面編程的庫。開發人員不知道(甚或不關心),他們只需要專注于交付他們關心的特性的業務價值。
我們還使用 WCF 許多其他方面的特性,如:
命名管道、事務性隊列編程模型、嚴格(不是鼓勵)基于接口的設計、安全特性、進程隔離、錯誤屏蔽,等等。
如果 .NET Core 不提供 WCF(或同等的功能),我就會損失太多的生產力,無法為這種切換辯護。如果一個可以用在任何環境的平臺中包含所有這些強大的功能,那會很棒。想一下,WCF 的生產力加上更便宜的托管環境帶來的成本節省。那是巨大的業務價值。
Pavel Dvorak 甚至說 WCF 是他們使用 .NET 的原因:
完全支持在 .NET Core 包含服務器端“WCF”的觀點。我們剛剛完成了另一個相當大的、幾乎完全是服務器端的處理系統。起初,我們因為沒有使用 Microsoft/.NET 承受了巨大的壓力,主要是因為其他(開源)技術棧在用于“基于微服務的”(就像傳統的 Web 服務)解決方案時所具備的相對優勢。但是,WCF 的優點,如嚴格基于契約的編程模型,特別是命名管道綁定,端點和綁定的靈活性(是的,聲明式方法/可配置性是一個優勢),安全性,工具如日志的可擴展性,在系統增長,需要擴展性、性能及可維護性時,這些優勢非常關鍵,而且,管道代碼真得非常少。很明顯,下一步是恰當的容器化(我們一直等待 Nano Server),總之,能夠把系統移植到下一代運行時平臺,而又不會對當前的質量造成任何損失。
在話題“Server side WCF #1200”中,你可以看到更多開發人員支持使用 WCF 開發的例子。
為什么最初不包含 WCF Hosting?
和以前一樣,一個答案是,那是個簡單的人力問題。只有這么多開發人員,他們不可能什么都做。來自微軟的 Ron Cain 解釋說:
鄭重聲明,我們不是故意把缺失的 .NET Framework WCF 特性排除在 .NET Core WCF 之外。不如說,最初的目標是,在處理其他 WCF 關鍵任務特性之前,在 .NET Core 中支持所有現有的 Windows Store WCF API(都是面向客戶端的)的特性。為了讓它可以跨平臺,移植 WCF 的許多工作都涉及重新實現 WCF 所依賴的 OS 級庫(如套接字層、加密等),或許,這有助于我們理解現狀。因此,支持 WCF 特性通常要首先針對每個平臺替換 OS 級的庫。這也許有助于理解 .NET Core 不再提供 WCF 中的“W”。
這就是為什么從你那里聽到什么特性最重要如此有價值的一個原因,因為那讓我們可以更深入地探討這樣的問題,“在 Linux 上實現特性X需要什么庫?在 OS X 上呢?”等等。請繼續提出建議和具體的方案!
為什么不使用 REST?
對于 WCF,最常見的抱怨是它與 ASP.NET WebAPI 和 REST 存在冗余關系。對此,J?rg Lang 回應道:
服務之間的消息很重要,在開發企業后端時,REST 不會奏效。它缺少太多其他人提到的東西。因此,.NET Core 當然應該支持事務、隊列消息、命名管道、可擴展性。
因此,.NET Core 必須以這種或另外一種方式提供那些東西。如果把它叫做 WCF,我也不介意。也許,這是個修復某些 WCF 弱點的機會,如過于復雜的配置,代之以基于慣例的方法。
除了 MSMQ 或服務總線外,你還應該/必須支持其他消息框架。一般來說,支持 AMQP 應該會不錯,包括各種消息模式。
Agustin M Rodriguez 附和了那種想法:
WCF 一直用于提供高質量可擴展的服務,利用跨網絡事務(System.Transactions)提供可靠性。如果 .NET Core 不支持 WCF,那么我們會失去太多通過廣泛的 WCF 攔截器鏈獲得的“免費”益處,包括日志、行為和上下文流。
在 Scott Hurlbert 看來,WCF 的吸引力是它根本不需要使用 HTTP:
這兩行代碼只是一個例子,但是,有趣的是,這里的 Binding 和端點模式是組件:
Binding binding = new BasicHttpBinding (); IMySimplestService proxy = ChannelFactory<IMySimplestService>.CreateChannel (binding, new EndpointAddress ( "http://localhost:8008/" ) ); proxy.Echo ("Hello");這很有趣,因為那意味著,通過交換那些來自 WCF 的組件可以實現通過 Http/https、UDP、TCP-IP、MSMQ、NetPipes 及其他一些協議和端點模式通信。
按照我的理解,在近來的 Web 開發中,許多人已經忘記了 HTTP 之外的其他東西,但是,如果你的應用增長,那么你可能會發現自己希望有能力使用完全相同的代碼,但是指向一個隊列的端點。令人遺憾的是,大多數其他的框架會讓用戶自己重新實現隊列系統,而不僅僅是重定向它。
更別提事務(也已淡出了視線——直到它們必不可少)和各種形式的身份驗證和加密等等特性了。
Catalin Pop 同樣關注 WCF 如何成為各種協議之上的抽象:
是的,有許許多多的框架,大的,小的,更“企業級的”或者更面向 1337 h4x0r 的,提供不同的選項和模式,有的嚴格,有的靈活……這就是問題所在……沒有基線。
WCF 應該幫助處理所有這些完全不同的選項,提供一種統一而抽象的通信框架,作為 .NET 開發的基線。
你希望使用二進制 protocolX,而不是 http,當然,你可以插入它。你希望使用 Oauth2,而不是 windows 驗證,當然,配置一個,你希望使用 NServiceBus 插入 NServiceBus 綁定。你希望以某種形式轉換上下文,如網絡事務范圍,你也可以把那個插入。應用程序編程模型保持不變。
從 .NET 應用程序的角度來看,RPC 本身并不是一個復雜的東西,你調用一個方法或者接收一個調用。使其變得復雜的是眾多方法和框架,以及你可以在其中實現的安全性、格式、特性和其他選項。
這些地方應該引入 WCF,那是 WCF 的長項。
“WCF 太復雜”
對于 WCF,一種常見的批評是太復雜。公平地講,它經常以一種非常復雜的方式實現。但是,就像 Scott Hurlbert 所指出的那樣,不一定必須那樣。下面是一個完整的 WCF 客戶端和服務器所需的代碼。
這是一個 ENTIRE Wcf 服務:
[ServiceBehavior]public class MySimplestService : IMySimplestService { ? ?public string Echo ( string pInput ){ ? ? ? ?return $"I heard you say: {pInput}";} }這是接口:
[ServiceContract]public interface IMySimplestService {[OperationContract] ? ?string Echo ( string pInput ); }好吧,也許托管這個服務很難。不。下面是服務托管和調用。這是全部的代碼:
var myServ = InProcFactory.CreateInstance<MySimplestService, IMySimplestService>(); Console.WriteLine ( myServ.Echo ("Hello World") );只是還沒有達到企業級的質量,而且很簡單。
我認為,WCF 已經獲得了一個奇怪的壞名聲,因為人們以一種難以置信的復雜方式實現它。不管你信不信,對于 .NET,這就是網絡兩端所需的全部。借助來自 iDesign 的 ServiceModelEx 框架,你甚至可以動態構建一個代理:
Binding binding = new BasicHttpBinding (); IMySimplestService proxy = ChannelFactory<IMySimplestService>.CreateChannel ( binding, new EndpointAddress ( "http://localhost:8008/" ) ); proxy.Echo ("Hello");嚴格來說,那四行代碼(來自包含結構代碼在內的 17 行代碼里)創建了一個企業級服務,它是代理,進行服務調用。它沒老化,那是生產力。
注意,甚至是這其實都比你需要的東西多。如果你在使用一個代理生成器,那么服務類可以作為自己的服務契約,而不需要一個單獨的接口。
反對 WCF 的機會成本論據
Blake Niemyjski 總結了反對 WCF 的真正理由:機會成本和過去糟糕的體驗:
我認為,創建服務器端 WCF 的投入是不值得的,應該優先考慮類似 SignalR 這樣的工具。WCF 客戶端配置總是那么困難,我討厭它:(,如果我錯了,請幫我糾正……但是,為什么 Web API 不是要選擇的方法……它是輕量級的,而且能給你構建應用所需要的所有東西,從任何平臺只需要一個簡單的調用即可……
把安全、事務、發布/訂閱留給實現者……
還有其他幾位開發人員也贊同“WCF 與 VB.NET”不值得投入。(這些爭論似乎把 WCF 和 VB.NET 看作是相同的主題。)不過,Catalin Pop 不同意這種觀點:
[把安全、事務、發布/訂閱留給實現者……]是任何人都能給出的最糟糕的建議。安全永遠不應該留給實現者,那從來都是最糟糕的安全漏洞的源頭……安全專家真得很少,或者說,很少有開發人員有能力恰當地實現安全細節,這項工作是由不足1% 的程序員完成的。
服務器端 WCF 情況如何?
早在去年 6 月,Jeffrey T. Fritz 寫道:
有非常多的是 WCF 團隊,我們正致力于開發可以確保兼容 Windows 10、Windows Server 和 Windows 容器的特性。
在 Build 大會上,我們做了一次非常成功的演示,第一次展示了我們的 Windows 容器。該領域的工作還在進行中,我們計劃繼續這些領域的投入。
WCF for .NET Core 是我們重點關注的,我們正在和 ASP.NET Core 團隊合作,優先進行這項工作。在可以公開發布的時候,我們會分享更多細節。
雖然 WCF 所需的部分底層庫已經移植到了 .NET Core,并且/或者添加到了 .NET Stardard,但是,WCF Hosting 本身并沒有實際的進展。在 3 月份,一個題為“請做決定:服務器端 WCF”的獨立話題被創建,并且打上了 .NET 3.0 里程碑的標簽。
特別是最近,Immo Landwerth 寫道,“我們不會在 .NET Core 3.0 的時間框內引入[……]WCF Hosting,但是,我們稍后會根據用戶的反饋來做。”
GitHub 提供了?WCF 的源代碼,遵循 MIT 開源許可協議。因此,理論上講,由社區支持的 WCF for .NET Core 版本是可行的。
原文鏈接:http://www.infoq.com/cn/articles/WCF-Net-Core-Debate
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結
以上是生活随笔為你收集整理的关于.NET Core是否应该支持WCF Hosting的争论的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在 ASP.Net Core 中使用
- 下一篇: ASP.NET Core 2.0使用Au