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