快速搞懂.NET 5/.NET Core应用程序的发布部署

背景

.NET Framework时代,.NET 应用程序大多直接部署运行在Windows服务器上。无论部署exe,还是IIS站点、或是Windows Service,编译后的程序直接copy、简单配置部署上即可。

有了.NET Core之后,.NET应用程序完美支持跨平台部署。

支持跨平台部署运行,.NET 5/.NET Core的应用程序面临着多平台,多场景的部署需求。比如说:部署在Windows、Linux、MaxOS...,OS层面是否需要部署.NET Runtime运行时,.NET Runtime运行时的版本选择,等等。

因此,今天我们研究一下.NET 5/.NET Core应用程序的部署发布。

两种应用程序发布模式

1. 以自包含的方式发布应用程序

这种模式包含.NET运行时和应用程序及其依赖项的应用程序。我们可以在未安装.NET运行时的操作系统上运行它。

总结一句话:把.NET Runtime运行时打包到程序运行目录中,应用程序运行的主机不需要安装.NET Runtime运行时。

2. 以依赖于框架的方式发布应用程序

生成一个仅包含应用程序本身及其依赖项的应用程序。应用程序的运行环境必须单独安装.NET运行时。

总结一句话:不包含.NET Runtime运行时,只有应用程序本身和依赖的应用程序。应用程序运行的主机需要单独安装应用程序所需的.NET Runtime运行时。

NET 5/.NET Core的应用程序的发布指令:dotnet publish

dotnet publish -将应用程序及其依赖项发布到指定的文件夹中,以方便后续部署到目标托管系统。

关于dotnet publish的使用说明,可以参考以下链接:https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?WT.mc_id=DT-MVP-5003918

dotnet publish [<PROJECT>|<SOLUTION>] [-c|--configuration <CONFIGURATION>] [-f|--framework <FRAMEWORK>] [--force] [--interactive] [--manifest <PATH_TO_MANIFEST_FILE>] [--no-build] [--no-dependencies] [--no-restore] [--nologo] [-o|--output <OUTPUT_DIRECTORY>] [-p:PublishReadyToRun=true] [-p:PublishSingleFile=true] [-p:PublishTrimmed=true] [-r|--runtime <RUNTIME_IDENTIFIER>] [--self-contained [true|false]] [--no-self-contained] [-v|--verbosity <LEVEL>] [--version-suffix <VERSION_SUFFIX>]dotnet publish -h|--help

dotnet publish 将编译应用程序,读取其在项目文件中指定的依赖项,然后将结果文件集发布到目录中。输出包括以下内容

  • 具有dll扩展名的程序集中的中间语言(IL)代码。
  • 一个.deps.json文件,其中包含项目的所有依赖项
  • 一个.runtimeconfig.json文件,它指定应用程序期望的共享运行时,以及该运行时的其他配置选项(例如,垃圾收集类型)。
  • 应用程序依赖的应用程序,从NuGet缓存目录复制到输出文件夹中。

从上述描述中,我们可以发现,通过dotnet publish指令,我们可以编译应用程序,生成并输出指定运行环境的交付物。

我们新建一个.NET 5的Console应用程序,同时引用Newtonsoft.Json Nuget包。

Main函数的代码:

using System;

namespace NET5PublishExample{    class Program    {        static void Main(string[] args)        {            var msg = Newtonsoft.Json.JsonConvert.SerializeObject('Hello .NET 5!');            Console.WriteLine(msg);            Console.ReadKey();        }    }}

首先,编译一下这个工程dotnet build,这一步很重要。然后,使用命令行执行dotnet publish指令:

我们看一下F:\GitHub\Source\Repos\NET5PublishExample\bin\Debug\net5.0\publish\目录下生成的文件:

正如上面所说,输出包括以下内容

  • 具有dll扩展名的程序集中的中间语言(IL)代码:NET5PublishExample.dll
  • 一个.deps.json文件,其中包含项目的所有依赖项NET5PublishExample.deps.json
  • 一个.runtimeconfig.json文件,它指定应用程序期望的共享运行时,以及该运行时的其他配置选项(例如,垃圾收集类型)。NET5PublishExample.runtimeconfig.json
  • 应用程序依赖的应用程序,从NuGet缓存目录复制到输出文件夹中。Newtonsoft.Json.dll

同时,还生成了一个Windows平台的可执行文件:NET5PublishExample.exe,双击可以执行:

另外,使用dotnet NET5PublishExample.dll,也可以直接执行:

然后有几个疑问:

  • NET5PublishExample.dll是不是可以跨平台运行?
  • 在Linux、MacOS平台下有没有对应的可执行文件?

带着这2个问题,我们继续往下研究?

dotnet publish生成的可执行文件和跨平台二进制文件

自包含的方式发布应用程序,依赖于框架的方式发布应用程序。这两种发布模式默认情况下都会生成特定于平台的可执行文件和跨平台二进制文件。

1. 可执行文件

可执行文件不是跨平台的。它们特定于操作系统和CPU体系结构。因为Windows和linux下的可执行文件的结构和内容是不同的,所以可执行文件是分操作系统的。

这里我们示例2个平台的可执行文件:

① windows-x64平台

② Linux-x64平台

使用的dotnet publish指令 dotnet publish -r linux-x64 --self-contained false

生成的可执行文件:

2. 跨平台的二进制文件

将应用程序发布为依赖于框架的dll文件形式时,就会创建跨平台的二进制文件。该dll文件以项目命名。例如,如果您有一个名为应用程序NET5PublishExample,文件名为NET5PublishExample.dll创建。

以这种方式发布的应用程序dotnet <filename.dll>可以通过命令运行,可以在任何平台上运行。

关于自包含的发布选项和示例

以自包含的方式发布应用会生成特定于平台的可执行文件

输出发布文件夹包含应用程序的所有组件,包括.NET库和目标运行时。该应用程序与其他.NET应用程序隔离,并且不使用本地安装的.NET运行时。因此无需下载并安装.NET 运行时。

可执行二进制文件针对指定的目标平台生成。例如,如果您有一个名为NET5PublishExample的应用程序,并且发布了Windows的自包含可执行文件,则会创建NET5PublishExample.exe文件。对于Linux或macOS发布,将创建一个NET5PublishExample文件。目标平台和体系结构-r <RID>由dotnet publish命令的参数指定。有关RID的更多信息,请参见.NET RID目录。

如果应用程序具有特定于平台的依赖项,例如包含特定于平台的依赖项的NuGet程序包,则这些依赖项将与应用程序一起复制到publish文件夹中。

这种模式的优势有哪些呢?

  1. 控制.NET版本:可以控制与应用程序一起部署的.NET版本。
  2. 指定运行的平台:因为必须为每个平台发布应用程序,所以我们需要确定应用程序将在何处运行。如果.NET引入了新平台,则必须先发布针对该平台的版本,然后才能在该平台上运行您的应用程序。

同时也带来了以下问题:

  1. 更大的部署内容:应用程序包括.NET运行时和所有应用程序依赖项,所以所需的下载大小和硬盘空间大于依赖于框架的版本。
  2. 难以更新.NET版本.NET Runtime:(随应用程序分发)只能通过发布新版本的应用程序进行升级。但是,.NET将根据应用程序运行的计算机上框架库的需要更新关键的安全补丁。

例如:

示例1:发布一个独立的应用程序,创建macOS 64位可执行文件,同时包含了.NET 运行时

dotnet publish -r osx-x64

生成的文件列表如下:包含macOS 64可执行文件NET5PublishExample,以及包含了对应macOS 64平台下的.NET 运行时

示例2:发布一个独立的应用程序,创建Windows 64位可执行文件,同时包含了.NET 运行时

 dotnet publish -r win-x64

生成的文件列表如下:包含Windows 64可执行文件NET5PublishExample.exe,以及包含了对应Windows 64平台下的.NET 运行时

关于依赖框架的发布选项和示例

发布为依赖框架的应用程序是跨平台的,并且不包含.NET运行时。应用程序的运行需要单独安装指定版本的.NET运行时

应用程序的跨平台二进制文件可以使用dotnet <filename.dll>命令运行,并且可以在任何平台上运行。如果应用程序使用具有特定于平台的实现的NuGet包,则所有平台的依赖项都将与应用程序一起复制到publish文件夹中。

可以通过将-r <RID> --self-contained false参数传递给dotnet publish命令来为特定平台创建可执行文件。当-r参数被省略,为当前平台创建一个可执行文件。具有目标平台特定于平台的依赖关系的任何NuGet软件包都将复制到publish文件夹中。

这种模式带来的优势有:

  1. 小型部署:仅分发应用程序及其依赖项。.NET运行时和库由用户安装,所有应用共享运行时。
  2. 跨平台:应用程序和任何基于.NET的库都可以在其他操作系统上运行
  3. 使用最新的.NET运行时:该应用程序使用目标系统上安装的最新运行时。这意味着应用程序会自动使用最新的.NET运行时修补版本。

同时也带来了以下问题:

  1. 需要预安装.NET 运行时:仅在主机系统上已安装应用目标的.NET运行时版本时,应用才能运行。
  2. .NET可能会更改:.NET运行时和库可能会在运行该应用程序的计算机上更新。

例如:

示例1:发布一个当前平台的依赖框架的跨平台应用程序,不包含.NET 运行时,将与dll文件一起创建一个针对当前平台的可执行文件。

dotnet publish

使用dotnet NET5PublishExample.dll,可以直接运行(本机已经安装.NET运行时,NET5PublishExample.dll是跨平台的二进制文件

示例2:发布一个依赖框架的跨平台应用程序(Linux 64位),不包含.NET 运行时,将创建一个Linux 64位可执行文件以及dll文件。

dotnet publish -r linux-x64 --self-contained false

使用dotnet NET5PublishExample.dll,可以直接运行(本机已经安装.NET运行时,NET5PublishExample.dll是跨平台的二进制文件

ReadyToRun编译选项

通过将应用程序程序集编译为ReadyToRun(R2R)格式,可以改善.NET应用程序的启动时间和延迟。R2R是一种提前(AOT)编译的形式。

R2R二进制文件通过减少应用程序加载时即时(JIT)编译器需要完成的工作量来提高启动性能。与JIT产生的代码相比,二进制文件包含相似的本机代码

但是,R2R二进制文件较大,因为它们既包含中间语言(IL)代码(某些情况下仍然需要此代码)和同一代码的本机版本。仅当发布针对特定运行时环境(RID)(例如Linux x64或Windows x64)的应用程序时,R2R才可用。

总结一下:通过R2R方式,可以直接将代码编译为Native Code,减少.NET 程序第一次加载时JIT编译带来的性能消耗,以提升.NET应用的首次加载性能。类似于ngen的程序集预加载。关于Ngen可以参考这个链接:ngen

对应的dotnet publish指令选项: dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=true

以上是.NET 5/.NET Core应用程序的发布部署的一些研究和分享。

推荐一个不错的知识链接:https://docs.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent?WT.mc_id=DT-MVP-5003918

(0)

相关推荐

  • 【翻译】.NET 5 Preview 1 发布

    去年年底,我们发布了.NET Core 3.0和3.1.这些版本添加了桌面应用程序模型Windows Forms(WinForms)和WPF,ASP.NET Blazor用于构建SPA应用程序和用于构 ...

  • 使用cmd命令行(.NET Core CLI)来启动ASP.NET Core 应用程序的多个实例

    本章主要和大家分享下如何使用cmd命令行(.NET Core CLI)来启动ASP.NET Core 应用程序的多个实例,以此来模拟集群. .NET Core 命令行接口 (CLI) 工具是用于开发. ...

  • 重大更新:aardio 调用 .Net 更简洁了

    标准库 dotNet 最新版进行了大幅改进,现在调用 .Net 代码更简洁了,在 aardio 中调用 .Net 将会像调用 aardio 自己一样简单.dotNet 库函数文档以及相关范例都进行了同 ...

  • 【翻译】.NET 5 Preview8发布

    今天,.NET 5预览8发布了,对于.NET5.0的功能开发已经完成了,这必须要排除待处理的bug,预览8是最后一次预览版本.预计11月正式的.NET5.0版本发布之前还将发布两个正式之前的候选版本, ...

  • 在 Azure App Service 上运行 .NET 6 预览版

    dotNET跨平台 昨天 以下文章来源于汪宇杰博客 ,作者汪宇杰 汪宇杰博客微软最有价值专家(MVP)汪宇杰,致力于Azure..NET等技术方向.无广告,不卖课,做纯粹的技术公众号.博客地址 htt ...

  • Windows平台部署Asp.Net Core应用

    一. 简介 Asp.Net Core 部署方式有两种:依赖框架和独立部署. 1. 框架依赖的部署: 顾名思义,依赖框架的部署 (FDD) 依赖目标系统上存在共享系统级版本的 .NET Core. 由于 ...

  • 一文看懂:什么是.NET Core以及.NET Core能做什么?

    我们都知道.NET Core是一个可以用来构建现代.可伸缩和高性能的跨平台软件应用程序的通用开发框架.可用于为Windows.Linux和MacOS构建软件应用程序. 与其他软件框架不同,.NET C ...

  • So Easy - 在Linux服务器上部署 .NET Core App

    .NET Core 是微软提供的免费.跨平台和开源的开发框架,可以构建桌面应用程序.移动端应用程序.网络应用程序.物联网应用程序和游戏应用程序等.如果你是 Windows 平台下的 dotnet 开发 ...

  • ​可转债还不知道?这5个问题,帮你快速搞懂可转债

    当看到2019年持有可转债平均收益率在16%的时候,当大家都在可转债打新的时候,你是不是还在云里雾里?不知道可转债到底是怎么回事?具体怎么打新怎么中签?有多少收益? 接下来说说可转债具体是怎么回事. ...

  • 怎样看懂消防工程CAD图纸?教你四招,快速搞懂

    想快速看懂消防工程图,首先要对消防系统分类组成有一定的了解,仔细看清楚总平面图,然后把图纸设计说明和图例浏览一遍,其中有各种符号标示需要熟记,然后再去看系统图,只要多花点时间就没问题,自然而然就能看下 ...

  • 初学微距,摄影“老司机”传授8个建议,快速搞懂微距摄影

    一.选择拍摄位置和天气 拍摄微距,大多喜欢拍摄昆虫,其次是花卉植物,所以挑选拍摄位置和选择适当的天气是很重要的. 以拍摄昆虫为例,拍摄位置首先挑选在公园.树林等植物覆盖率较高的地方,更容易寻找到昆虫进 ...

  • 快速搞懂「活性污泥法」,主要把握这4点!

    本篇讲活性污泥法,初识活性污泥主要把握好以下4点内容. 01 微生物和活性污泥是一回事儿不?   这两个概念有一定相似性.重合性,但又不尽相同. 微生物我们前面讲过了,就是肉眼不可见的微小生命体:而活 ...

  • 一篇文章,让你快速搞懂新能源汽车充电系统

    俗话说"想要马儿跑,先让马儿吃点草:要想马儿跑的久,得让马儿先吃饱." 对于新能源汽车来讲又何尝不是呢? 要想续航里程跑的远,动力电池的储能得跟的上,同时后续的充电操作也不能被忽略 ...

  • 财务报表基本选股方法,快速搞懂股票财务分析,你也能看懂财报

    大家好,今天讲一下财务分析,如何来分析股市,从财务层面来观察股市.财务分析的我们之前提到过一些,财务分析,简单来讲的主要是分为五个指标来观察: 核心财务指标 毛利率.净利率.市盈率.市净率.净资产收益 ...

  • 新手入门必学经典法式蛋糕体之“乔孔达蛋糕”,一篇快速搞懂!

    新手甜点师刚开始学习制作产品的时候,往往会被配方中各种蛋糕胚的名称搞得晕头转向. 比如戚风蛋糕胚.海绵蛋糕体.达克瓦兹蛋糕体等等,各种蛋糕体之间的区别和搭配方式,对于新手甜点师来说都需要花很多时间和功 ...

  • 赛道模型:如何快速搞懂一家公司?

    三生 物语 有趣.有用的模型 0.导论 概念: 你想了解一家公司,在这个时代相对来说是比较容易的,但了解只是搞懂的基础.当你看到一家公司时,不能陷入某个孤立的点,要对市面上的各种分析言论有冷静的判断力 ...

  • 快速搞懂欧包为何割纹,更有4种必学割包手法!

    欧包虽然在口味上可能不及软面包那般柔软可口,但它有个最特别的地方,那就是欧包的表面割纹.割纹可以体现面包师的匠心工艺,可以为面包增添一丝点缀. 对于面包师而言,欧包的割纹可不仅仅只是为了好看,更有重要 ...