解讀ASP.NET 5 & MVC6系列(4):核心技術與環境配置
asp.net 5是下一代的asp.net,該版本進行了全部重寫以適用於跨平臺,新新版本中,微軟引入瞭如下工具與命令:DNVM、DNX、DNU。
DNVM(.NET Version Manager):由於要實現跨平臺的目錄,微軟提供了DNVM功能,DNVM是ASP.NET最底層的內容,他是一組Powershell指令碼,用於啟動指定版本的ASP.NET執行環境,並且可以在同一臺機器的同一時間點上通過使用Nuget工具來管理各種版本的ASP.NET執行環境(DNX),以及進行相應的升級操作。
DNX(.NET Execution Environment):DNX是ASP.NET程式的執行環境,用於啟動並執行ASP.NET程式。該執行環境包括了編譯系統、SDK工具集、Native CLR宿主環境。可以使用DNVM管理各種版本的DNX,如dnvm list
dnvm install 0.1-alpha-build-0446
則可以將指定版本的DNX安裝到.dnx資料夾,你可以在%USERPROFILE%\.dnx\runtimes
目錄下找到已安裝所有版本的DNX。不同的作業系統有不同的DNX版本。
dnx.exe:dnx.exe是用於啟動自宿主環境(Self-Hosting)的命令列工具,在使用命令列程式碼進行自宿主環境啟動程式時,dnx負責查詢並呼叫CLR Native Host,dnx命令是整個執行環境的入口點,你可以使用dnx run
來啟動程式。
dnu(DNX Utility):是一個命令列的包管理器,包含在DNX內,所以只要安裝了DNX,就可以使用dnu命令, 其可以用於恢復程式包、安裝程式包、部署程式包等等,比如把project.json裡自定義的程式集自動下載下來進行使用。
DNX架構及執行原理
DNX是ASP.NET程式執行的核心,其遵循如下兩個準則:
- DNX應該是自包含的,DNX在解析完應用程式依賴樹以後才能知道要使用哪個Core CLR包,所以在得到解析樹之前,DNX是無法載入任何CLR的,但Roslyn編譯器除外。
- 依賴注入(Dependency Injection,簡稱DI)貫穿著整個系統棧,DI是DNX的一個核心部分,所有DNX上的類庫都構建在DI之上。
DNX執行環境的分層架構如下:
Layer 0:Native Process
該層的功能非常簡單,主要就是用於查詢並呼叫Layer 1
裡的CLR Native Host
,並將系統相關的引數傳遞給native host
DNX.exe
來處理這個事情,而IIS也提供了一箇中介(網站bin目錄下提供一個AspNet.Loader.dll
)可以將請求轉發給Native Host
;而Linux和Mac則通過其相應版本的dnx來支援這項功能。
DNX用法:
dnx.exe --lib {paths} --appbase {path} [ProgramName]
--lib {paths}:程式集dll的儲存地址(一般是引用的第三方程式集和專案預編譯程式集),該地址是Layer 2層的託管程式碼入口點可以載入程式集的地方。
--appbase {path}:程式儲存的目錄,預設為%CD%。
[ProgramName]:程式名稱,該程式所在的程式集(或者是含有Programe::Main
的dll)儲存在--lib
路徑下,預設值是appbase\project.json
裡的name。大多數情況下,該名稱都是包含著載入鏈的程式宿主(Microsoft.Net.ApplicationHost
)。但是,如果你的程式包含了入口點(Main方法),並被編譯到--lib
目錄下的話,你就可以使用該程式集的名稱作為[ProgramName]
,這種方式將完全忽略載入鏈並直接啟動你的程式。
Layer 1 : CLR Native Host
這一層的內容依賴於你所選擇呢CLR版本,該層有如下兩個職責:
- 啟動CLR,啟動哪個CLR取決於你選擇的CLR版本。如果是
Core CLR
,該層會載入coreclr.dll
,配置並啟動執行環境,然後建立應用程式域(AppDomain
),以便執行所有的託管程式碼。 - 呼叫託管程式碼的入口點(
Layer 2
),一旦Native Host
的入口點返回了該執行緒,就會把CLR的執行緒清理乾淨並關閉,比如,解除安裝應用程式域(AppDomain
)並停止執行環境。
Layer 2:Managed Entry Point
Layer 2層(託管程式碼入口)是編寫託管程式碼的第一層,其職責如下:
- 建立
LoaderContainer
(其包含需要的ILoaders
),ILoader
負責根據程式集的名稱來載入程式集。CLR需要一個程式集的話,LoaderContainer
就會使用其ILoader
來解析所需要的程式集。 - 從
--lib
的路徑目錄下,用根ILoader
來載入程式集,並解析其依賴。 - 呼叫程式的主入口點。
Layer 3:Application host/Application
如果開發人員將整個程式編譯成程式集放在libpath
目錄下,那該層就是你的應用程式了。使用的時候,將含有程式入口點的程式集名稱作為[ProgramName]
的引數傳入即可,Layer 2
層會直接呼叫該程式集。
不過,一般其它情況下,都會使用一個應用程式宿主(Application host
)來解析程式的依賴內容並啟動執行程式。Microsoft.Net.ApplicationHost
是執行環境提供的應用程式宿主,並擁有如下職責:
- 解析
project.json
裡定義的各種依賴程式集。 - 將一個
ILoader
新增到LoaderContainer
,以便從各種地方(如原始碼、NuGet、Roslyn等)載入相應的程式集。 - 呼叫程式集的入口點,將其作為下一個引數,傳遞給DNX.exe。
Layer 4:Application
這一層,就是開發人員開發的程式,其執行在應用程式宿主之上。
環境配置:
要對ASP.NET 5程式的執行環境DNX進行配置,首先需要安裝並配置DNVM,不同的作業系統安裝DNVM的時候不太一樣,我們在這裡大概講解一下。
Windows安裝命令:
//需要安裝powershell 3.0
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/aspnet/Home/master/dnvminstall.ps1'))"
Linux:
curl -sSL https://raw.githubusercontent.com/aspnet/Home/master/dnvminstall.sh | sh && source ~/.dnx/dnvm/dnvm.sh
Mac OS X:
在Mac上,首先要安裝Mac系統本身的包管理器Homebrew(http://brew.sh
),並使用brew tap aspnet/k
命令將指定到ASP.NET5相關的git儲存庫,比如執行如下命令:
brew install dnvm
該命令將會自動從ttps://www.nuget.org/api/v2
上下載最新的DNX,下載以後,如果你的系統不識別dnvm的話,你還需要再執行一下如下語句:
source dnvm.sh
上述DNVM安裝以後,系統會將dnvm檔案複製到C:\Program Files\Microsoft DNX\Dnvm
目錄,並將C:\Program Files\Microsoft DNX\Dnvm
目錄新增到環境變數中,以便全域性都可以使用。注意:這裡只是安裝了DNVM,並沒有安裝任何版本的DNX,要安裝DNX的話,可以通過執行dnvm或dnvm help來查詢相關的命令,具體命令如下:
dnvm upgrade [-x86][-x64] [-svr50][-svrc50] [-g|-global] [-proxy <ADDRESS>]
- 從feed源安裝最新版的DNX
- 為已安裝的DNX設定一個預設(default)別名
- 將DNX bin新增的使用者PATH環境變數中
- -g|-global 在全域性內進行安裝(其它使用者也可以使用)
- -f|-force 強制更新成最新版(即便最新版已經安裝過了)
- -proxy 訪問遠端伺服器的時候使用特定的地址作為代理
dnvm install <semver>|<alias>|<nupkg>|latest [-x86][-x64] [-svr50][-svrc50] [-a|-alias <alias>] [-g|-global] [-f|-force]
- | 從feed源安裝指定的DNX
- 從本地檔案系統安裝指定的DNX
- latest 從feed源安裝最新版的DNX
- 將DNX bin新增到當前命令列的path環境變數中
- -p|-persistent 將DNX bin新增到系統PATH環境變數中
- -a|-alias 對指定安裝的DNX設定別名
- -g|-global 在全域性內進行安裝
- -f|-force 強制安裝指定的DNX(即便該版本已經安裝過了)
dnvm use <semver>|<alias>|none [-x86][-x64] [-svr50][-svrc50] [-p|-persistent] [-g|-global]
- | 將DNX bin新增到當前命令列的path環境變數中
- none 將DNX bin從當前命令列的path環境變數中刪除
- -p|-persistent 將DNX bin新增到系統PATH環境變數中
- -g|-global 組合使用-p將使用者PATH修改成系統PATH
dnvm list //列出所有已安裝的DNX版本
dnvm alias //列出所有定義了別名的DNX版本
dnvm alias <alias> // 顯示定義了別名的DNX名稱
dnvm alias <alias> <semver> [-x86][-x64] [-svr50][-svrc50] //給指定的DNX版本設定別名
管理程式集的dnu命令和feed源配置
通過dnu命令進行包管理的時候,通常使用如下命令:
dnu restore
:查詢程式的所有依賴包,並將其全部下載到packages目錄,該命令會下載整個依賴包以及這些依賴包所依賴的其它依賴包。
dun install <package id>
:該install命令用於下載指定的程式包並新增到程式中。
dun publish
:該命令會將你的程式打包到一個可以執行的自包含目錄中。其會建立如下目錄結構:
output/
output/packages
outpot/appName
output/commandName.cmd
packages
目錄包含所有應用程式需要的程式包。appName
目錄包含所有應用程式的程式碼,如果引用了其它專案,則在引用的其它專案也會建立各自專案的同級目錄,即生成的目錄會和AppName同級。publish
命令,會將project.json中的commands節點中的各種命令,分別生成響應的命令列檔案,如commands裡的web命令,我們就可以通過dnx web
(格式:dnx <command>
)開執行它。
由於dnu在內部使用了Nuget命令,進行程式包的管理,所以使用的時候要正確配置Nuget的feed源,目前ASP.NET 5相關的包都在myget feed上,所以我們需要新增這個feed才能正常執行。這些配置資訊在Windows下的%AppData%\NuGet\NuGet.config
(或者*nix下Mono使用的~/.config/NuGet/NuGet.config
)檔案中進行管理。示例如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetvnext/api/v2/" />
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
</packageSources>
<disabledPackageSources />
<activePackageSource>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
</activePackageSource>
</configuration>
在VS2015下,則可以直接通過Tools--> Options--> Nuget Package Manager--> Package Sources來設定,示例如下圖:
另外需要注意一下,上述feed的地址是asp.net5的每日構建版本,如果你想使用穩定的里程碑版(如1.0.0_alpha4),則需要使用如下地址
https://www.myget.org/F/aspnetmaster/api/v2/
。
Web Server支援
微軟在實現DNX的時候提供了幾種Web伺服器支援,具體分別如下:
Microsoft.AspNet.Loader.IIS (Helios)
該伺服器用於在IIS上載入ASP.NET5程式,以便和IIS程序整合,同時繞過了System.Web
從而帶來效能上的提升,可以支援Windows認證、靜態檔案訪問等功能。其原理是將IIS與NDX之間做一個橋接。
Microsoft.AspNet.Server.WebListener (WebListener)
該伺服器通過Microsoft.AspNet.Hosting
在IIS之外載入程式、服務、work role等,它直接執行在Http.Sys核心驅動之上,僅消費少許效能,從中可以受益於埠共享,Windows認證等功能。
Microsoft.AspNet.Server.Kestrel (Kestrel)
該伺服器通過Microsoft.AspNet.Server.Kestrel
在IIS之外載入執行,其設計被用於跨平臺的Web服務(Windows、Mac、Linux等等)。
參考內容
- https://github.com/aspnet/Home/wiki/DNX-structure
- https://github.com/aspnet/Home/wiki/Command-Line
- https://github.com/aspnet/Home/wiki/Version-Manager
- https://github.com/aspnet/Home/wiki/Package-Manager