hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

深切明白.NET Core的基元(二) - 同享框架

2019-11-18杂谈搜奇网50°c
A+ A-

原文:Deep-dive into .NET Core primitives, part 2: the shared framework
作者:Nate McMaster
译文:深切明白.NET Core的基元(二) - 同享框架
作者: Lamond Lu

本篇是之前翻译过的《深切明白.NET Core的基元: deps.json, runtimeconfig.json, dll文件》的后续,这个系列作者临时只写了3篇,虽然有一些内容和.NET Core 3.0已不兼容了,然则大部份的道理还都是相通的,所以背面的第三篇我也会翻译。

  • 深切明白.NET Core的基元(一):deps.json, runtimeconfig.json, dll文件
  • 深切明白.NET Core的基元(二):同享框架
  • 深切明白.NET Core的基元(三):深切明白runtimeconfig.json

媒介

自.NET Core 1.0起,同享框架(Shared Framework)就已成为了.NET Core的重要组成部份。自.NET Core 2.1起,ASP.NET Core就已作为同享框架的第一次涌现。你可以历来注重过这一点,然则在设想它的时刻,我们阅历了许多重复和延续的议论。在本篇文章中,我们将深切同享框架并议论一些开发人员常常碰到的一些圈套。

基本部份

.NET Core运用可以在两种形式下运转, 分别是框架依靠形式(Framework - Dependent) 和自力运转形式(Self Contained) 。在我的Macbook上,一个最小的可自力运转的ASP.NET Core网站运用,约莫具有350个文件,文件大小统共是93MB。相对的,一个最小的框架依靠运用,约莫5个文件,文件大小统共239KB。

你可以以下敕令行生成基于两种差别形式的运用。

dotnet new web
dotnet publish --runtime osx-x64 --output bin/self_contained_app/
dotnet publish --output bin/framework_dependent_app/

当顺序运转的时刻,他们的功用是一样的。那末这两种形式有什么区别么?实在正如官网文档中的诠释:

框架依靠布置(framework-dependant deployment) 依靠目的中装置的.NET Core同享组件。自力布置(self-contained deployment)不依靠目的体系中装置的同享组件,顺序所需的一切组件都已包括在当前运用顺序中。

这篇官方文档(https://docs.microsoft.com/en-us/dotnet/core/deploying/)中很好的诠释了差别形式的上风。

PS: 作者当时写这边文章的时刻, 没有引入Framework-dependent executables (FDE),有兴致的同砚可以自行检察。

同享框架

这里,简朴的说,.NET Core的同享框架就是一个顺序集(*.dll文件)鸠合的目次,这些顺序集不需要涌如今你的.NET Core的运用目次中。这个目次是.NET Core的同享体系局限版本的一部份,一般你可以在C:\Program Filres\dotnet\shared中发明它。

当你运转dotnet.exe WebApi1.dll敕令时,.NET Core宿主顺序会

  • 尝试发明你的运用依靠的顺序集称号和版本
  • 在某些牢固位置中尝试查找该顺序集

这些顺序集可以在许多差别的位置被发明了,包括且不限于同享框架。在我之前的文章中,我重要诠释了假如经由过程deps.jsonruntimeconfig.json文件设置宿主顺序的行动。愿望相识更多的同砚,可以检察那篇文章。

.NET Core宿主顺序会读取*.runtimeconfig.json文件来肯定加载哪一个版本的同享框架。这个文件的内容相似:

{
  "runtimeOptions": {
    "framework": {
      "name": "Microsoft.AspNetCore.App",
      "version": "2.1.1"
    }
  }
}

这里,同享框架称号只是一个名字。依据商定,这个名字应当是以.App末端的,然则现实上它可以是任何字符串,比方"FooBananaShark"。

关于同享框架的版本,这里只是设置了一个最低的版本。.NET Core宿主顺序会依据设置,加载对应版本的同享框架,或许更高版本的同享框架,然则它永久不会加载比指定版本低的同享框架。

那末,我究竟装置了哪些同享框架呢?

运转dotnet --list-runtimes, 你就可以看到你电脑中装置了哪些同享框架,以及它们的版本和文件位置。

对照Microsoft.NETCore.App, AspNetCore.App以及AspNetCore.All

这里,以.NET Core 2.2为例。

框架称号 形貌
Microsoft.NETCore.App 基本运转时。它重要供应了System.ObjectList<T>string类,以及内存治理,文件治理,收集I/O, 线程治理等功用
Microsoft.AspNetCore.App 默许Web运转时。它重要供应了运用API建立Web服务器的功用,这里重要包括Kestral, Mvc, SignalR, Razor, 以及EF Core的部份功用。
Microsoft.AspNetCore.All 与第三方的集成库。它追加了EF Core + Sqlite的支撑,以及一些扩大功用, 比方Redis, Azure Key Valut等。(在.NET Core 3.0中已不再运用)

同享框架与Nuget包的关联

.NET Core SDK生成了runtimeconfig.json文件。在.NET Core 1和2中,SDK运用了项目设置中的两部份来肯定runtimeconfig.json文件中框架部份内容。

  • MicrosoftNETPlatformLibrary属性。关于一切.NET Core项目,它默许是Microsoft.NETCore.App
  • Nuget包治理东西的复原效果集,效果集合可以包括了雷同称号的包

这里针对一切的.NET Core项目, .NET Core SDK都邑增加一个隐式的包来援用Microsoft.NETCore.App。ASP.NET Core经由过程修正默许设置MicrosoftNETPlatformLibrary, 将其改成Microsoft.AspNetCore.App

然则这里需要注重,Nuget包治理东西不供应任何同享框架!不供应任何同享框架! 不供应任何同享框架! 重要的事变说三遍^_^。Nuget包治理东西只供应编译器运用的一些API,以及少许SDK。同享框架的猎取泉源可以是运转时装置器 https://aka.ms/dotnet-download, 或许捆绑在Visual Studio中,Docker镜像中,以及一些Azure服务器中。

版本前滚战略

正如我上面提到的,runtimeconfig.json只是指定了一个最小版本。现实运用的版本会依靠于一个版本前滚战略(细致内容可以参阅官方文档。比方

  • 假如运用运用的同享框架最小版本是2.1.0, 那末顺序最高会加载的同享框架版本是2.1.*。

针对这一部份,可以拜见《深切明白.NET Core的基元(三):深切明白runtimeconfig.json》

作者:《深切明白.NET Core的基元(三):深切明白runtimeconfig.json》后续会补上

分层的同享框架

在.NET Core 2.1版本中引入了分层同享框架的特征。

同享框架可以依靠于其他同享框架。引入此特征是为了支撑ASP.NET Core, 这个特征可以将顺序包的运转时存储转换为一个同享框架。

假如你检察一下$DOTNET_ROOT/shared/Microsoft.AspNetCore.All/$version/文件夹,你会发明一个名为Microsoft.AspNetCore.All.runtimeconfig.json的文件,其内容以下

$ cat /usr/local/share/dotnet/shared/Microsoft.AspNetCore.All/2.1.2/Microsoft.AspNetCore.All.runtimeconfig.json
{
  "runtimeOptions": {
    "tfm": "netcoreapp2.1",
    "framework": {
      "name": "Microsoft.AspNetCore.App",
      "version": "2.1.2"
    }
  }
}

多级检索

在.NET Core 2.0中引入了多级检索特征。

宿主顺序在启动时会探查多个位置,以寻觅适宜的同享框架。顺序首先会查找dotnet根目次,即包括一个dotnet.exe可执行文件的目次。这里我们可以经由过程设置DOTNET_ROOT的环境变量来掩盖此设置。依据此设置,顺序检索的第一个目次是:

$DOTNET_ROOT/shared/$name/$version

假如这个目次不存在,宿主顺序会尝试运用多级检索机制,检索预定的全局途径列表。这个机制可以经由过程设置全局变量DOTNET_MULTILEVEL_LOOKUP=0来封闭。默许情况下,预定的全局途径列表以下:

OS Location
Windows C:\Program Files\dotnet (64位历程) C:\Program Files (x86)\dotnet (32位历程) (检察源代码)
macOS /usr/local/share/dotnet (检察源代码)
Unix /usr/share/dotnet (检察源代码)

终究宿主顺序会在找到的全局目次中检索以下目次

$GLOBAL_DOTNET_ROOT/shared/$name/$version

ReadyToRun特征

同享框架中的顺序集,都是经由crossgen东西预优化过的。运用这个东西可以生成"ReadyToRun"版本的顺序集,这些顺序集都是针对指定操作体系和CPU架构优化过的。这里重要的机能提拔是,减少了JIT在启动时预备代码所消费的时候。

Crossgen相干文档:https://github.com/dotnet/coreclr/blob/v2.1.3/Documentation/building/crossgen.md

一些圈套

我置信每一个.NET Core顺序员都邑碰到以下圈套中的一部份。我将全力诠释这些题目是怎样发生的。

Http Error 502.5 Process Failure

到目前为止,开发人员,最常碰到的圈套是在IIS中或许Azure Web Services中托管ASP.NET Core运用顺序。这个题目一般发生在开发人员升级了一个项目,或许当运用布置的时刻,目的机械没有更新。这个毛病的真正缘由一般是运用所需版本的同享框架找不到,致使.NET Core运用顺序没法一般启动。当dotnet没法启动运用顺序时,IIS会返回HTTP 502.5的毛病,然则不会显现内部的毛病音讯。

"The specified framework was not found"

It was not possible to find any compatible framework version
The specified framework 'Microsoft.AspNetCore.App', version '2.1.3' was not found.
  - Check application dependencies and target a framework version installed at:
      /usr/local/share/dotnet/
  - Installing .NET Core prerequisites might help resolve this problem:
      http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
  - The .NET Core framework and SDK can be installed from:
      https://aka.ms/dotnet-download
  - The following versions are installed:
      2.1.1 at [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
      2.1.2 at [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]

这个毛病一般涌如今HTTP 502.5毛病以后,或许Visual Studio Test Explorer毛病。

如上所述,当runtimeconfig.json文件指定了一个框架称号和版本,然则经由多级检索特征和前滚战略以后,主机依旧没法找到一个适宜的框架版本的时刻,就会涌现以上毛病。

升级Microsoft.AspNetCore.App顺序集的Nuget包

Microsoft.AspNetCore.App顺序集的Nuget包,并不供应同享框架。它只是供应了C#/F#编译器运用的一些API以及少许SDK. 所以你必需要零丁下载并装置同享框架。

同时,由于前滚战略,你并不需要更新Nuget包的版本,来让你的顺序运转在新版本的同享框架中。

这多是ASP.NET Core团队的一个设想失误,我们没法将同享框架作为Nuget包涌如今项目文件中。同享框架所供应的顺序包并非一般意义上的顺序包。与大部份顺序包差别,它们不是自力更生的。我们愿望当项目运用<PackageReference>时,Nuget可以装置所需的一切援用,然则使人懊丧的是,这些特别顺序包的设想偏离我们希冀的形式。固然,如今我们已得到了种种发起来处理这个题目。我愿望它能早日完成。

在ASP.NET Core 2.1的新项目模板和文档中,微软向开发人员展现了,他们只需要在项目文件中增加以下的一行代码。

<PackageReference Include="Microsoft.AspNetCore.App" />

其他的<PackageReference>援用代码都必需要包括Version属性。只有当项目文件是以<Project Sdk="Microsoft.NET.Sdk.Web">开首的,那末以上这句与版本无关的顺序包援用才会起作用,而且这里只对Microsoft.AspNetCore.{App, All}顺序集包起作用。Web SDK将依据项中的其他设置, 比方:<TargetFramework><RuntimeIdentifier>, 来自动挑选一个适宜的顺序包版本。

假如你在包援用的部份到场的Version属性,并指定了版本,或许你没有运用Web SDK作为项目文件的开首,则没法运用此功用。这里我很难引荐一个好的处理方案,由于最好的完成体式格局是基于你对此的明白水温和项目范例的。

宣布修剪(Publish Trimming)

当你运用dotnet publish敕令宣布一个框架依靠的运用时,SDK会运用Nuget的复原效果(restore result)来决议哪些顺序集应当涌如今宣布目次中。有一些顺序集是经由过程Nuget顺序集包拷贝的,而有一些就不是,由于他们已涌如今同享框架中。

这很轻易发生一些毛病,由于ASP.NET Core作为同享框架和Nuget顺序包都是可用的。项目宣布修剪特征会尝试经由过程图形数学来搜检依靠通报,以及升级等,并以此挑选正确的顺序包文件。

下面我们以以下的项目援用为例:

<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.9" />

MVC现实上是Microsoft.AspNetCore.App的一部份,然则当挪用dotnet publish敕令宣布项目后,你会发明你的项目选用了升级后的Microsoft.AspNetCore.Mvc.dll顺序包,这个顺序包比Microsoft.AspNetCore.App中包括的2.1.1版本要高,所以终究Microsoft.AspNetCore.Mvc.dll会被拷贝到宣布目次中。

这就不太理想了,由于跟着你的运用顺序大小不停增进,你永久得不到ReadyToRun优化版本的Microsoft.AspNetCore.Mvc.dll

PS: 这个题目之前很少注重到,不过真的很罕见。

殽杂目的框架的别称与同享框架

假如简朴以为"netcoreapp2.0" == "Microsoft.NETCore.App, v2.0.0", 你就大错特错了。目的框架别称(Target Framework Moniker简称TFM)只经由过程项目文件中<TargetFramework>节点指定的。"netcoreapp2.0"只是愿望以人类友爱的体式格局来表达你要运用哪一个版本的.NET Core。

TFM的圈套在于它的称号太短了。它不能表达出多种同享框架,特定补丁的版本掌握,版本前滚,输出范例以及是自力宣布照样框架依靠宣布等内容。SDK会尝试从TFM揣摸许多设置,然则没法揣摸一切内容。

所以,更正确的说“netcoreapp2.0”意味着"Microsoft.NETCore.App v2.0.0及以上版本"。

殽杂项目设置

末了一个圈套和项目设置有关。在这里有许多术语和设置称号,它们不老是一致的。这些术语异常使人困惑,因而,假如殽杂了这些术语,也没有关联,那不是你的错。

下面,我就列出一些罕见的项目设置及实在际寄义。

<PropertyGroup>
  <TargetFramework>netcoreapp2.1</TargetFramework>
  <!--
    现实意义:
      * 从Nuget包剖析编译援用时运用的API鸠合的版本
  -->

  <TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks>
  <!--
    现实意义:
      * 运用两个差别的API鸠合版本举行编译。但这并不代表多层同享框架
  -->

  <MicrosoftNETPlatformLibrary>Microsoft.AspNetCore.App</MicrosoftNETPlatformLibrary>
  <!--
    现实意义:
      * 最顶层的同享框架称号
  -->

  <RuntimeFrameworkVersion>2.1.2</RuntimeFrameworkVersion>
  <!--
    现实意义:
      * 指定了Microsoft.AspNetCore.App顺序包的版本,这个版本就是最小的同享框架版本
  -->

  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  <!--
    现实意义:
      * 操作体系品种 + CPU架构
  -->

  <RuntimeIdentifiers>win-x64;win-x86</RuntimeIdentifiers>
  <!--
    现实意义:
      * 运转此项目可以运用的操作体系品种和CPU架构列表,你必需要经由过程RuntimeIdentifier设置挑选个中一个
  -->

</PropertyGroup>

<ItemGroup>

  <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.2" />
  <!--
    现实意义:
      * 运用Microsoft.AspNetCore.App作为同享框架
      * 最低版本2.1.2
  -->

  <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.2" />
  <!--
    现实意义:
      * 援用Microsoft.AspNetCore.Mvc顺序包
      * 现实版本2.1.2
  -->

  <FrameworkReference Include="Microsoft.AspNetCore.App" />
  <!--
    现实意义:
      * 运用Microsoft.AspNetCore.App作为同享框架.
  -->

</ItemGroup>

总结

同享框架作为.NET Core的可选功用,只管存在缺点,然则我以为关于绝大部份用户来讲,这是一个合理的默许设置。我依旧以为关于.NET Core开发人员来讲,相识背地的道理是一件功德,愿望本文是对同享框架功用的优越概述。我尽量的关联了一些官网文档和指南,以便你可以找到更多的信息。假如另有其他题目,请在下面宣布批评。

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
深切明白.NET Core的基元(二) - 同享框架

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282357.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>