41

关于.NET Core是否应该支持WCF Hosting的争论

 5 years ago
source link: http://www.infoq.com/cn/articles/WCF-Net-Core-Debate?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文要点

  • 本文试图回答“.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版本是可行的。

查看英文原文: The Argument for WCF Hosting in .NET Core


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK