.NET Framework時代,.NET 應用程序大多直接部署運行在Windows服務器上,固然也能夠經過Mono部署運行在Linux上。不管部署exe,仍是IIS站點、或是Windows Service,編譯後的程序直接copy、簡單配置部署上便可。linux
有了.NET Core以後,.NET應用程序完美支持跨平臺部署,.NET 5 Release後,沿襲了.NET Core應用程序發佈模式。json
支持跨平臺部署運行,.NET 5/.NET Core的應用程序面臨着多平臺,多場景的部署需求。好比說:部署在Windows、Linux、MaxOS...,OS層面是否須要部署.NET Runtime運行時,.NET Runtime運行時的版本選擇,等等。windows
所以,今天咱們研究一下.NET 5/.NET Core應用程序的部署發佈。緩存
1、兩種應用程序發佈模式安全
1. 以自包含的方式發佈應用程序服務器
這種模式包含.NET運行時和應用程序及其依賴項的應用程序。咱們能夠在未安裝.NET運行時的操做系統上運行它。框架
總結一句話:把.NET Runtime運行時打包到程序運行目錄中,應用程序運行的主機不須要安裝.NET Runtime運行時。函數
2. 以依賴於框架的方式發佈應用程序性能
生成一個僅包含應用程序自己及其依賴項的應用程序。應用程序的運行環境必須單獨安裝.NET運行時。ui
總結一句話:不包含.NET Runtime運行時,只有應用程序自己和依賴的應用程序。應用程序運行的主機須要單獨安裝應用程序所需的.NET Runtime運行時。
2、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 將編譯應用程序,讀取其在項目文件中指定的依賴項,而後將結果文件集發佈到目錄中。輸出包括如下內容:
從上述描述中,咱們能夠發現,經過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\目錄下生成的文件:
正如上面所說,輸出包括如下內容:
同時,還生成了一個Windows平臺的可執行文件:NET5PublishExample.exe,雙擊能夠執行:
另外,使用dotnet NET5PublishExample.dll,也能夠直接執行:
而後有幾個疑問:
NET5PublishExample.dll是否是能夠跨平臺運行?
在Linux、MacOS平臺下有沒有對應的可執行文件?
帶着這2個問題,咱們繼續往下研究?
3、dotnet publish生成的可執行文件和跨平臺二進制文件
自包含的方式發佈應用程序,依賴於框架的方式發佈應用程序。這兩種發佈模式默認狀況下都會生成特定於平臺的可執行文件和跨平臺二進制文件。
1. 可執行文件
可執行文件不是跨平臺的。它們特定於操做系統和CPU體系結構。由於Windows和linux下的可執行文件的結構和內容是不一樣的,因此可執行文件是分操做系統的。
建立可執行文件時,同時能夠選擇將應用程序發佈爲自包含或依賴於框架。
以自包含的方式發佈應用程序包括該應用程序的.NET運行時,而且該應用程序的用戶沒必要擔憂在運行該應用程序以前安裝.NET。能夠直接執行!
發佈爲與框架相關的應用程序不包括.NET運行時和庫。僅包括應用程序和第三方依賴項。須要安裝.NET 運行時。
這裏咱們示例2個平臺的可執行文件:
① windows-x64平臺
② Linux-x64平臺
使用的dotnet publish指令 dotnet publish -r linux-x64 --self-contained false
生成的可執行文件:
2. 跨平臺的二進制文件
將應用程序發佈爲依賴於框架的dll文件形式時,就會建立跨平臺的二進制文件。該dll文件以項目命名。例如,若是您有一個名爲應用程序NET5PublishExample,文件名爲NET5PublishExample.dll建立。
以這種方式發佈的應用程序dotnet <filename.dll>能夠經過命令運行,能夠在任何平臺上運行。
4、關於自包含的發佈選項和示例
以自包含的方式發佈應用會生成特定於平臺的可執行文件。
輸出發佈文件夾包含應用程序的全部組件,包括.NET庫和目標運行時。該應用程序與其餘.NET應用程序隔離,而且不使用本地安裝的.NET運行時。所以無需下載並安裝.NET 運行時。
可執行二進制文件針對指定的目標平臺生成。例如,若是您有一個名爲NET5PublishExample的應用程序,而且發佈了Windows的自包含可執行文件,則會建立NET5PublishExample.exe文件。對於Linux或macOS發佈,將建立一個NET5PublishExample文件。目標平臺和體系結構-r <RID>由dotnet publish命令的參數指定。有關RID的更多信息,請參見.NET RID目錄。
若是應用程序具備特定於平臺的依賴項,例如包含特定於平臺的依賴項的NuGet程序包,則這些依賴項將與應用程序一塊兒複製到publish文件夾中。
這種模式的優點有哪些呢?
同時也帶來了如下問題:
例如:
示例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 運行時
5、關於依賴框架的發佈選項和示例
發佈爲依賴框架的應用程序是跨平臺的,而且不包含.NET運行時。應用程序的運行須要單獨安裝指定版本的.NET運行時。
應用程序的跨平臺二進制文件可使用dotnet <filename.dll>命令運行,而且能夠在任何平臺上運行。若是應用程序使用具備特定於平臺的實現的NuGet包,則全部平臺的依賴項都將與應用程序一塊兒複製到publish文件夾中。
能夠經過將-r <RID> --self-contained false參數傳遞給dotnet publish命令來爲特定平臺建立可執行文件。當-r參數被省略,爲當前平臺建立一個可執行文件。具備目標平臺特定於平臺的依賴關係的任何NuGet軟件包都將複製到publish文件夾中。
這種模式帶來的優點有:
同時也帶來了如下問題:
例如:
示例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是跨平臺的二進制文件)
6、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
周國慶
2020/2/15