@liuhui0803
2017-05-11T08:11:18.000000Z
字数 8726
阅读 4294
开发
微软
.NET
.NETCore
架构和设计
摘要:
上周五,ASP.NET Core悄然进行了调整,现仅支持.NET Core 2.0。这意味着在Mono或完整版.NET Framework基础上运行的ASP.NET Core 1.0/1.1应用程序将无法升级至ASP.NET Core 2.0,这一新版本预计会在未来2-3个月内发布。由于未经公开讨论或正式说明就对平台做出如此重大的改变,此举惹怒了很多重量级开发者。
正文:
上周五,ASP.NET Core悄然进行了调整,由原本同时支持.NET Standard 1.和.NET 4.改为仅支持.NET Core 2.0。这意味着在Mono或完整版.NET Framework基础上运行的ASP.NET Core 1.0/1.1应用程序将无法升级至ASP.NET Core 2.0,这一新版本预计会在未来2-3个月内发布。由于未经公开讨论或正式说明就对平台做出如此重大的改变,此举惹怒了很多重量级开发者。
跨框架支持曾被视作ASP.NET Core的一个重要特征。其基本思路在于,用户可以在立即切换至ASP.NET Core的同时继续使用自己原有的服务类、代码库,以及第三方库。随后等到.NET Core发展到与.NET Framework保持一致后,还可以随时切换回来。
ASP.NET开发经理Eilon Lipton解释了此番改动背后的原因:
没错,对于ASP.NET Core 2而言,大部分库主要是以.NET Core 2为目标的,这是为了能顺利地使用.NET Standard TFM中暂不可用的新增API。对于需要以诸如Microsoft.Extensions.*、Entity Framework Core,以及其他少数库等多个平台为目标的代码,需要继续使用.NET Standard。
在询问微软为何不直接开发包含必要API的.NET Standard 2.1后,Kévin Chalet继续问到:
我的问题很简单:RTM之前,你们是否由可能重新调整/撤销这些改动,让用户能够继续在.NET Desktop上使用ASP.NET Core 2.0软件包,还是说.NET Desktop上的ASP.NET Core 2.0已经彻底没戏了?(这对包括我在内的很多人都是个很不利的因素)。
虽然不打算全文引用,但很多开发者均对此表达了类似的顾虑。
Scott Hanselman试图通过自己对于在.NET Framework中继续使用ASP.NET Core的主要理由安抚开发者:
AD – 老实说,如果希望直接调用LDAP,这方面还存在比较大的问题。虽然目前依然可以通过Windows Auth进行身份验证,但我们计划今年夏天针对Core 2.0提供更具体的DirectoryServices名称空间。
Drawing – 这也是个问题。我们计划今年夏天为Core 2.0提供相关能力,但在此之前,这些Netstandard选项也广泛存在于ImageSharp、ImageResizer、Mono等选项中。
COM自动化 – 这一特性在Core 2.0中从未实现过,如果希望自寻烦恼,开发者当然可以使用PInvoke,如果这样的烦恼还嫌不够,还可以为net461+进程使用本地WebAPI。
与WFP应用实现代码共享 – 没错,这在Netstandard2.0中是完全可行的。
随后Scott Hanselman重申说:
.NET Core正在经历快速的并行发展,发展速度远远超过了完整版.NET Framework,其实这是好事。通过基于.NET Core 2.0(别忘了,这可是.NET Standard的超集)构建ASP.NET Core 2.0应用,这意味着可以用远超NetFx甚至Netstandard的速度进行开发。
虽然.NET Core 2.0是.NET Standard的超集,但并不是.NET Framework的超集。Kévin Chalet写到:
很多被重新引入.NET Core 2.0的“古老的”API实际上都是历史残余,(从功能上来看)从来未能正常使用过。更不用提.NET Core目前依然缺乏很多API,甚至特意省略了对很多领域的支持(IdentityModel、WCF服务器、远程、完整的AppDomain支持等)。
试图劝说大家可以“安全地”将自己使用.NET Desktop开发的ASP.NET Core 1.0应用迁移至使用.NET Core开发的ASP.NET Core 2.0应用,在我看来这是彻头彻尾的谎言。
谈到该技术的发展速度,他又补充说:
我觉得(大部分)人们关心的并不是这个。很多人根本不需要发展速度如此快的库,他们更想要稳定的库,借此按自己的节奏将其集成于老应用,同时无需担心兼容性风险。
包括Allan Lindqvist在内,很多开发者还担心此举可能造成社区产生嫌隙。
很多真心认可Asp.NET Core 1.1的开发者感觉自己被背叛了,他们现在可能会不愿意切换至没有了Core的2.0版。这么说也许显得不合理,但我想说的是,很多人都会产生这样的感觉,同时他们将不得不应对其他更保守的同事提出的各种问题。
这些重要吗?Asp.NET Core2/.NET Core2会因此而“亡”吗?不会,但会拖累用户的接受速度,让整个生态系统支离破碎,在我看来这才是最大的悲哀。我希望大家都能使用2.0版所包含的所有出色技术,但是将交叉编译能力限制为只能用于.NET Standard无疑会对此产生影响。当然,对大部分固守原有代码库的普通开发者来说这不算是个问题,但只不过是将问题转嫁给了他们的经理。
另一个顾虑在于,这个决定是内部私下做出的,并没有公示或公开讨论。Demis Bellot认为:
由于官方事先并未公布这一消息或听取用户反馈,也没有进行意见征集或给出合理的理由,这个决定“似乎”是完全与社区无关的,也没有对现有.NET生态可能产生的影像进行任何分析,可能导致整个生态系统在未来几年内变得支离破碎。取消对.NET v4.x的支持,意味着很多企业无法通过足够平滑的方式将现有代码迁移至ASP.NET的全新开发模型。这一举措不能让他们加速接受.NET Core,反而会打消他们这样做的念头,严重的碎片化会进一步导致整个.NET生态一分为二。我觉得最终的结果将会与Python 2/3的情况差不多,不可避免得受到碎片化的伤害,造成十几年都无法挽回的后果。
继续说回有关库支持的问题,Gulbanana列举了一些他本人需要,但.NET Core不支持的特性:
我们是Core CLR和可移植能力的忠实“铁粉”,我们已经将自己的很多组件移植到了多个不同的Netstandard。目前我们已经通过Linux托管了一个应用,预计未来会有更多应用这样做。然而很快将完全无法进行移植了!目前我们一些依然在维护的代码依赖下列技术:
NTLM身份验证(包括一些与令牌和SPN有关的高级应用场景)。
System.Drawing如上所述(这方面有个趣闻:我们需要使用一些古老的图像格式,例如TIFF,而新的OSS库根本不支持)。
连接至WCF/SOAP API - 依然在我们的代码中大量使用。
Windows Crypto API(包括RSACng、ECDSA,以及用于PKI令牌的CSP)。
WPF GUI - 我们的客户短期内不会升级至 Windows 10,但就算升级了,他们也不会使用商店应用。
Microsoft Office Interop实现数据导入和导出(主要使用Access和Excel)。
Visual Studio的扩展能力
第三方插件,例如Oracle ADO.NET提供程序
Core CLR可能永远不会支持其中的某些技术,但这些技术也有自己的价值,同时也是新应用开发工作的基础。我们需要一种能支持这些技术的.NET版本。目前我们的立场还是可控的:我们会隔离“遗留”(实际上也就是依赖具体平台的)依赖项,将其隔离在符合net461规范的专有组件内。如果某个业务应用依赖这些功能,则可以针对Netfx建立依赖项。虽然我设想以后的应用很少需要这样做,但我不觉得可以彻底避免这种做法。
有关csproj和SDK的这一切做法都是因为互操作实在太重要了。ASP.NET Core是大家希望实现互操作的诱因,我觉得取消这一点是不合理的。当然,“虽然可以单向加载引用,但最终很可能在运行时失败”这种做法绝对算不得互操作。
Tim Miller进一步补充说:
我们目前的Web应用中还用到了OData和SignalR,在可以升级前必须继续使用ASP.NET Core。然而我最不希望遇到的情况就是,由于对ASP.NET Core 1.x的支持被削弱而导致我们陷于其中,并且因为目前使用的框架部件不被支持,我们还无法进行迁移。我认为ASP.NET Core最终将全面取代ASP.NET,也许前路还很长,但终究有一天会实现的。因此我很不希望现在用ASP.NET MVC 5重写我们的UI(少量内容虽已重写,但主要是因为规模小,所以过程简单而已),而仅仅几年后当ASP.NET寿终正寝后又使用ASP.NET Core再次重写。
大家关注的另一个重点是Entity Framework。虽然有EF Core,但很少有开发者会用它而不使用EF 6,因为EF Core仅支持老版本所具备的部分功能。实际上Reddit等论坛上对此有一种普遍意见:ASP.NET Core应当用于新的项目,但在变得更稳定之前,开发者应避免使用.NET Core和EF Core。
对Louis Lewis来说,最大的障碍在于硬件的检测:
从你的这个清单来看,我们目前正在使用但尚未移植的就是system.management DLL了。具体来说,我们需要使用硬件标识符,这是为了在Azure服务总线和我们的全部许可服务器和客户端程序包之间自动建立链接。我不禁在想,这些东西已经不再是API了,是否会对我们造成某些严重的问题?
Christian Weiss补充说:
当然了,Azure Service Fabric库也不支持.NET Core,对我们来说这也是个障碍。
修正方案
为了回应所有这些批评,Damian Edwards已经公布了一个修正方案。
在.NET Framework上对ASP.NET Core 1.x的支持将至少再延长一年(直到2019年7月)。我们每年还会再次考虑这一时限,并保证会在ASP.NET Core 1.x支持终止前12个月发布通知(也就是说,我们会在2018年7月宣布是否继续延长一年至2020年7月)。(题外话:现在就考虑2020年的事情,有没有人被吓着?没有?好吧,那看来只有我了)。
新发布的SignalR将以ASP.NET Core 1.x为目标并为其提供完整支持(今年底发布)。
我们将继续更新ASP.NET Core 1.x,以便支持新的语言版本或其他特性,这一做法与System.Web的处理方式无异。
运行于.NET Core 1.x的ASP.NET Core 1.x,其支持截止期限为2018年7月(无变化)。
运行于.NET Core 2+的ASP.NET Core 1.x,其支持期限与运行于.NET Framework的ASP.NET Core 1.x维持一致。这是为了确保受支持的ASP.NET Core与受支持的.NET Core之间始终有相互重叠的部分,同时还支持运行于.NET Framework,这样客户就可以陆续将自己的代码移植到可支持的技术中。
.NET Core 1.x(作为运行时)的支持无变化,将于2018年7月结束。使用ASP.NET Core 1.x的客户需要在那之前迁移至.NET Core 2.0或.NET Framework(或迁移至运行于.NET Core 2.0的ASP.NET Core 2.0)。
今年我们会将System.DirectoryServices和System.Drawing移植至.NET Core(完整支持、跨平台,今年夏季至少提供Windows预览版)。
在这之后还要将ServiceBase移植至.NET Core(用于支持.NET Core Windows Services)。目前没有具体时间安排,不过已经确定了这是后续要做的工作(随着工作的进展,时间安排无疑才能更精确)。我们还会根据客户反馈调整后续工作安排。
目前我们并无将System.ServiceModel(服务器端WCF)移植至.NET Core的计划。但可能会进一步完善WCF for .NET Core,并根据用户反馈添加新的功能,例如HTTP消息加密。
如果能早点公布这些信息,也许大家的抱怨会少一些,David Fowler已经提到了微软希望从.NET Standard中抽身的原因。
我们已经确认会将“字符串”作为.NET Core需要继续完善的主要目标,大家提出了五花八门的想法,其中之一提到默认使用UTF8格式的字符串(兼容性问题还有很多,且听我一一道来)。
我们打算解决的另一个问题是:能够使用任何连续内存创建更低开销的数组/字符串切片(Slice)。我们已经增添了Span,并在努力实现对应的Buffer。这也许意味着String和Array所实现的新接口使得我们可以创建完全无需分配的切片。
这就为String提供了新方法,可在无需每次都分配数组的情况下进行拆分。
但这会对Int、UInt等(TryParse)接受Span和Span的内容造成负担。
这还会产生可以接受Span的全新编码例程。
Buffer和Span可以让我们用统一的方式呈现内存,我们还希望对网络栈进行升级,借此传递可以接受Span或Buffer的Pre-pinned buffer。
Kestrel将在2.x版本期间(目前目标为2.1版)实现HTTP2,这就要求需要通过SSL流的新API来处理ALPN。
运行于.NET Core的HttpClient支持双工流(Duplex streaming),借此将可以通过SignalR以HTTP的方式用一个非WebScoket的HTTP请求实现流端点。
我们还通过HttpClient和System.NET.Http为头解析器的实现创建了分支,并更改了名称,这样就可以改进使其同时支持.NET Framework和.NET Core。.NET Core已经包含这些改进的副本,但并未投入使用,因为其实并不需要改进(未获使用)。
与线程有关的很多新原语(Primitive)需要新的API,借此可以塑造全新的适用场景,不过这些只是我的个人看法。
虽然这些原因可以安抚一些人,但Stefan Olson也归纳了大部分开发者的想法:
在我看来,似乎ASP.NET Core将运行于.NET Core而非.NET Standard?那么我依然纳闷.NET Standard价值何在?是否在诞生的那一天就注定了它最终会被抛弃?
我觉得更合理的做法是,ASP.NET Core需要依赖.NET Standard 2.1,因为该框架目前还不具备用户需要的某些功能。那么我们只能继续等待完整的.NET Framework支持这些额外的功能,随后才能使用最新版ASP.NET Core。这样是可行并且合理的。
但他们竟然抛弃了Standard,使其完全发挥不出作用(不知道我对目前这种混乱的局面理解是否正确)。
目前.NET Standard面临的局面还不是那么悲催,它依然是一种向第三方库同时提供.NET Framework和.NET Core能力的好方法。
挫败感还在继续
Stack Overflow的Nick Craver通过实例论证了很多团队可能产生的沮丧。在花了大量时间将他们的代码移植到ASP.NET Core + .NET Framework之后,他们觉得自己的努力做了无用功:
基本功能方面依然存在差距。移植到1.x的工作基本上完全就是一种旁侧(Lateral)项目,可供我们使用的功能极为有限。2.x版在某种程度上来说还算值得进行升级,但我们也无法保证最终一定就会这么做。有很大可能我们花费大量时间、成本以及精力移植到1.x版的努力最终会搁浅,因为随后还需要依赖完整的Framework。我不希望自己公司在这方面打赌碰运气。最终我们能得到的支持可能远远比不上目前使用的ASP.NET 4.x。
除非这一点能有所改变,否则我们的应用不会移植到ASP.NET Core,而我们所有的库可能会面临比缺乏内部测试更糟糕的麻烦。
真心希望你们能重新考虑这个决定。希望有朝一日可以让Stack Overflow充分利用我们贡献出来的数千小时个人时间,帮助.NET Core平台更上一层楼。
Quentin对此表示了赞同:
没错,具体原因我很理解,真希望我能说“早就猜到有这样的一天”,但不事先通知就放弃,这一点真的让人很不爽。
和其他厂商类似,我们也有应用生态,有诞生于十几年前甚至更早之前的库,有很多MVC 3、4、5应用,有控制台应用,有Windows服务,有成百上千行代码。相比其他一些技术,情况完全没有糟糕到必须要进行升级的地步。
最近我们使用ASP.NET Core 1.1开发了几个新的Web应用,这就必然要以完整的4.6.2版Framework为目标。这些应用大量运用了我们现有的共享库。我们已经将大量开发工作时间用于处理project.json,随后是新出现的.csproj,这么做只是为了在同一个解决方案中混合使用新老.csproj,回退至VS15将只能使用古老的.csproj类型,破碎的System.Dependencies,冗烦的程序集绑定问题,构建和发布问题……等等等等。
而现在我们已经展翅高飞进入到一个死胡同里。是否就这样放弃数个人月的开发工作,或投入更多时间来查明哪些代码可用哪些又不可用,然后想方设法进行升级,接下来才能知道这样的做法到底可不可行。
不能说我完全不赞同目前的方向和必要性,只不过希望能提前通知一下大家。
秘密的意图
这一系列意见的关键在于,微软对这次的改动已经“蓄谋已久”了,只不过他们没有公开而已。David Fowler认为:
这也是1.1版ASP.NET Core的生命周期被延长(虽然还是会结束)的主要原因。我们需要确保SignalR可以正常使用,因为那是我们选择使用ASP.NET Core 2.0的重要原因。于此同时,归根结底这并不是ASP.NET Core的目标,它们的目的始终在于作为统一的.NET Core平台的一个组成部分发布给用户。
对此Scott Sauber回应说:
我是真正见证了每一版ASP.NET的发展过程(包括Hanselman和Glenn对Docker进行的3小时排错……因为我就是个技术宅),我会阅读博客,我随时刷Twitter,我每年参加两次以上的技术会议,我会参加用户组,我会参与各种活动,但我从未见过有人针对ASP.NET Core的发展规划进行过此类讨论。相反,我只听到每个人都在说“它可以跨平台运行”,没错,感觉就像你想坐下时有人把椅子挪走了。我甚至做过有关ASP.NET Core的演讲,并且自己也说过“它可以在每个平台上运行”这样的话,现在感觉自己打了自己的脸。我认为,像是ITT那些游走在技术前沿的人也许能接受这样的消息,而这肯定会招致不少抵制。感觉当更多无法快速适应的开发者以及他们的经理,也就是比ITT更为保守的那群人听说了这个消息后,情况可能会变得更糟糕。
有关.NET Framework的其他顾虑
这个讨论还谈到了.NET Framework。David Fowler认为:
Span本身有一个可以运行在各种平台的可移植版本,但我不确定.NET Framework上的实现是否是其中速度最快的。这些API即将加入.NET Framework,它们可以充分利用Span,但可能会比Span本身慢一些,毕竟范围非常大。我们上一次在.NET Framework中更改字符串和数组又是什么时候呢?
问题不在于Span本身,而在于.NET Framework造成的影响,以及它和其他有关.NET Core的改进是否能够顺利实现。Matt Nischan认为:
我们一直认为,要在可行的情况下尽可能使用各种新颖的库(例如Kestrel),但依然要继续等待.NET Core变得更稳定(很高兴我们耐心等待了,而原因仅仅在于这工具自身的变化),或者等待有更酷的Core版本最终融入到Framework中。我认为大部分人会假设,Corefx的各种改进,就算不是全部,只是大部分被最终纳入Framework vNext或vNext+1,那结果也是极好的。然而(从超过3万的浏览量)看起来,围绕Framework的各种改变并不能塑造一个面向未来的平台。
Frans Bouma补充说:
确实是个好问题:关于将.NET Core的功能向后移植到完整版.NET的计划,到底还剩下些什么?看到这里我发现,完整版.NET真是太脆弱了,代码的移植需要投入大量时间(它的改进实在是太慢),甚至可能随时中断(有这种可能,只是不知道具体会有多棘手),因此我认为这种情况应该不会经常发生。
这就可能产生两个结果:或者向后移植到完整版.NET是可行的,只不过发布频率没那么高(例如每六个月或者每年);或者整个过程非常复杂容易出错。如果是前一种情况,只要按照步调进行就好,不过这不能让用户买单,并且别再使用后者作为借口。如果是后一种情况,那么说Netstandard是“异端邪说”就是最合理的结论了,毕竟未来最重要的还是.NET Core的API不是吗?
作者:Jonathan Allen、Jeff Martin,阅读英文原文:ASP.NET Core Drops Support for .NET