在IIS上發佈並運行ASP.NET Core

 
當構建一個ASP.NET Core應用程序而且計劃將其運行在IIS中時,你會發現Core應用程序和以前版本的ASP.NET程序在IIS中的運行方式是徹底不同的。

在本篇文章中,你能夠了解ASP.NET Core是如何運行在IIS上下文中的,怎樣才能把ASP.NET Core應用程序發佈在IIS上。html

IIS和ASP.NET Core

關於ASP.NET Core,最重要的一點就是它託管於一個獨立運行的控制檯程序。它不用託管在IIS中,也不依賴IIS。ASP.NET Core應用程序有自託管的Web服務器,而且可使用這個自託管的服務器實例在內部處理請求。web

不過,你能夠將IIS做爲ASP.NET Core應用的前置代理。這是由於Kestrel是一個最基礎的Web服務器,它並不像IIS這樣一個完整Web服務器,有一些特性Kestrel是不支持的。爲了提供80/443前置端口,推薦在Windows平臺上使用IIS,由於kestrel沒法直接提供這種使用方式。對於IIS(或其餘反向代理)來講,即使是在ASP.NET Core應用程序中,也仍將做爲服務器的一部分扮演着重要的角色。如今咱們一塊兒看一下IIS是如何和ASP.NET Core應用相配合的。
 

經典的ASP.NET託管

在正式瞭解ASP.NET Core託管前,讓咱們回顧一下運行ASP.NET應用程序經典ASP.NET模式。
 
 
在經典ASP.NET應用程序中,全部一切都託管在IIS工做進程中(w3wp.exe),這也被稱爲IIS應用程序池。ASP.NET程序被託管在應用程序池中,而且被按照IIS內建的ASP.NET託管特性所實例化。當請求從http.sys傳入到ASP.NET應用程序管道時,本地運行時管理器會實例化一個表明應用程序的.NET運行時,同時引入HttpRuntime對象用來處理這個請求。來自http.sys的請求被派送到對應的應用程序池和HttpRuntime實例的託管站點。

ASP.NET Core與IIS

ASP.NET Core則徹底不一樣,它並非運行在IIS的工做進程中,而是獨立運行的。它運行於控制檯應用程序之中,控制檯中則運行了Kestrel Web服務器組件。Kestrel做爲一款.NET Web服務器的實現,它在吞吐量性能方面作了不少工做。它能夠快速未來自網絡的請求接入到應用程序中,可是它僅僅是一個最基本的Web服務器。它沒有相似IIS的Web管理服務,也沒有IIS那麼多的功能。json

當選擇在Windows平臺上運行時,將IIS做爲Kestrel的前置服務器能夠得到額外一些基礎功能。好比經過主機頭的80/443端口轉發、處理生命週期管理和證書管理等。後端

下圖展現了IIS做爲Web前置服務器與運行的ASP.NET Core應用程序的關係:
 
 

ASP.NET Core程序獨立運行在控制檯應用程序中,並經過dotnet運行時命令調用。它並無被加載到IIS工做進程中,可是IIS卻加載了名爲AspNetCoreModule的本地Module,這個Module用於執行外部的控制檯程序。瀏覽器

AspNetCoreModule是做爲ASP.NET Core Server Hosting Bundle的一部分被安裝在服務器上的。緩存

當安裝ASP.NET核心服務器託管捆綁(或在開發機上安裝.NET Core SDK)時,AspNetCoreModule就會出如今IIS的本地Module列表中:
 
 

AspNetCoreModule做爲IIS本地Module,在IIS處理管道週期的最開始就能hook到請求,緊接着就將全部請求重定向到後端的ASP.NET Core程序。這裏是全部的請求,也就是說即使是頂級的映射Handler,好比aspx。這些都將從IIS管道中分流到ASP.NET Core中處理。這意味着,無法簡單的將ASP.NET Core和其餘框架放在同一個站點(虛擬目錄)中。這看起來有點退步了,由於在此以前能夠混合使用不一樣框架。安全

這裏IIS站點(虛擬目錄)仍然須要配一個IIS應用程序池,不過這個應用程序池應當使用No Managed Code。這裏應用程序池僅僅做爲前置代理接受請求,因此它不用實例化.NET運行了。
 
 

AspNetCoreModule的做用是確保在第一個請求來以前你的程序已經加載好了,而且保證ASP.NET Core在因爲某些緣由崩潰後的重啓工做。這實際上和被WAS(Windows Activation Service)管理的經典ASP.NET程序是同樣的。服務器

當程序運行起來後,AspNetCoreModule會處理接入的Http請求,並將其路由到ASP.NET Core程序中。網絡

所以,來自Web的請求進入到內核模式,由http.sys驅動程序路由到IIS的主要端口(80)或SSL端口(443)上。請求接着被轉發到ASP.NET Core程序配置的非80/443端口中。從本質上來講,IIS在這裏扮演的是反向代理的角色,它僅僅簡單的將請求轉發到運行在Kestrel Web服務器上不一樣端口的ASP.NET Core程序裏。app

Kestrel接收到請求,並將其推送到ASP.NET Core的中間件處理管道中,該處理管道稍後將處理這個請求並將請求傳入到應用程序邏輯代碼中。HTTP的輸出結果會再次傳回到IIS,接着IIS將結果經過Internet返回給初始化這個請求的客戶端,它多是瀏覽器、手機客戶端或者一個應用程序。

AspNetCoreModule配置在位於應用程序根目錄的web.config文件中。配置文件定義了用來加載.NET Core程序的啓動命令(dotnet)和參數(應用程序主dll)。web.config文件中的配置標明瞭須要加載的應用程序模塊和啓動DLL的根目錄。

下面就是web.config的例子:
 
 1 <?xml version="1.0" encoding="utf-8"?><configuration>
 2   <!--
 3     Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
 4   -->
 5   <system.webServer>
 6     <handlers>
 7       <add name="aspNetCore" path="*" verb="*"
 8         modules="AspNetCoreModule" resourceType="Unspecified" />
 9     </handlers>
10     <aspNetCore processPath="dotnet" arguments=".\AlbumViewerNetCore.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
11   </system.webServer>
12 </configuration>
 
這裏能夠看到AspNetCoreModule引用了dotnetexe和.NET Core程序中包含Main方法編譯入口點DLL。

還須要IIS麼?

前面已經討論過在Windows上運行ASP.NET Core時,推薦將IIS做爲前置代理。然而直接經過IP地址和端口也是能夠訪問Kestrel的,但仍是有理由能夠說服你不在生產環境中直接暴露應用程序。

首先,當你在單個服務器上運行多個應用程序,而且須要共享80和443端口時,直接運行Kestrel就不行了。Kestrel不支持多個80端口綁定到單個IP地址的主機頭路由方式。拋開IIS(其實是http.sys),目前爲止單獨使用Kestrel是沒法實現的(而且我想這也不在計劃中)。

運行在IIS中的AspNetCoreModule同時提供了必要的進程管理措施,它能夠確保程序在首次訪問前已經被加載好,也能夠確保程序持續運行即使在崩潰後也能夠從新啓動。AspNetCoreModule提供的必要進程管理來保證AspNetCore程序即使是在崩潰以後也始終可用。

讓IIS處理SSL請求也是很好的選擇,經過IIS的證書存儲區設置證書,並讓IIS正確處理SSL認證。從IIS出來到應用程序的請求能夠是一個非安全的HTTP請求。這意味着只有一個前置的IIS服務器須要證書,即使是你後面有多個真正提供http內容的服務器。

IIS還能夠提供靜態文件服務、靜態文件的gzip壓縮、靜態文件緩存、Url重定向和IIS本地能夠提供的其餘功能。IIS實際上在處理非應用程序請求時即好又高效,因此很值得利用IIS的這些優點。讓IIS處理它擅長的任務,讓剩下的動態任務傳遞給ASP.NET Core程序來處理。

當你將ASP.NET Core部署在Windows平臺上時,你會但願使用AspNetCoreModule的。

不要把IIS做爲開發時服務器

我常常會遇到相似這種問題:

我能夠像以前開發經典ASP.NET Web應用程序那樣在IIS中運行和調試ASP.NET Core程序麼?

讓咱們先把這個問題放一邊,幾乎沒有理由在開發過程當中使用IIS。的確,在過去,徹底在IIS中開發是有必要的,由於IIS和IIS Express二者在某些方面存在一些不一樣的行爲。

然而,在使用ASP.NET Core的狀況下就徹底沒有理由再考慮在開發過程當中使用IIS。這是爲何?由於ASP.NET Core程序並非運行在IIS內部的。不管是從IIS或IIS Express中的調用或直接從命令行使用dotnet run命令,實際運行的都是同一套代碼而且大多數狀況下是在徹底相同的運行環境中。在IIS內部運行就不能簡單的使用命令行環境下模擬了。

惟一可能須要在IIS下運行的一種緣由就是:IIS提供的一些依據HTTP服務的東西,是真正和ASP.NET Core的處理相分離的。可是,即使是這樣,這些特性也不會在調試應用程序上下文時用到。

「運行」IIS

在調試環境中,不能「僅僅運行IIS」,這是由於ASP.NET Core程序必須得先發布,而後才能執行。開發文件夾中並無包含全部運行程序所需的文件。當選擇「調試」或「運行」程序時,首先會將程序發佈到一個單獨的地方,再從那裏運行。因爲這個緣由,你Visual Studio的例子中就看不到IIS選項了。

若是非要在IIS下運行,那麼你得先將程序發佈到本地文件夾中,而後將該文件夾配置爲IIS的虛擬目錄或站點,接着就能夠運行了。

向IIS發佈ASP.NET Core程序

爲了在IIS下運行程序,第一步就是要將應用程序發佈出來。如今,提供了兩種發佈方式:

  • 使用dotnet publish命令
  • 使用Visual Studio的發佈功能

使用 dotnet publish

dotnet publish構建程序並將一個可運行、自託管的項目版本拷貝到磁盤的新位置。你能夠指定一個輸出文件夾做爲發佈文件的存放處。這與在經典ASP.NET中將Web站點發布到一個臨時文件夾相似。在ASP.NET Core中顯示選擇在某個路徑下發布程序,這樣文件再也不會隱藏,也不會四處複製。

典型的發佈命令多是這樣的:
 

這表示將程序發佈到c:\temp\AlbumViewerWeb。

打開這個文件夾,能夠看到這裏麪包含了原始的程序結構和全部依賴的nuget程序集。
 

IIS託管發佈文件夾指導

當應用程序發佈後,將其複製到服務器上(經過FTP或其餘方式),接着就能夠將IIS和這個文件關聯起來。

接下來先建立一個虛擬應用程序目錄:
 
 

要注意我建立的這個AspNetCore應用程序池,要把它的.NET運行時設置爲前面所說的非託管代碼。

如今,能夠瀏覽網站或虛擬目錄,應用程序同時也就跑起來了。

如今把本地發佈的網站拷貝到Web服務器上(經過FTP或直接拷貝文件或者其餘方式),設置好站點或虛擬目錄就能夠了。

從Visual Studio發佈

dotnet publish這步將整個項目拷貝到另外一個文件夾中,但這實際上並無將項目發佈爲網站(目前,還須要稍微等一會)。

使ASP.NET Core應用程序增量發佈是很是重要的,你須要使用MsDeploy來管理這麼多的依賴項,MsDeploy是做爲Visual Studio Web發佈功能的一部分。

目前,Visual Studio的圖形工具仍是有缺陷的的,可是底層的功能是支持的。這裏按照我作出的一些調整,而後就可使用了。

當你使用Visual Studio的RC2 Web工具和發佈對話框時,你發現沒法建立針對IIS的發佈概要。這裏只有文件和基於Azure的發佈選項,無法直接經過界面建立新的Web網站發佈。

不過,你能夠本身建立.pubxml並將其放在項目中\Properties\PublishProfiles文件夾內,這樣就能夠欺騙開發工具了。

特定版本的解決方法

很顯然,這個問題在RC2以後的版本會獲得更新。因此,當你在一個月後讀到本文的這些步驟時,請先確認下是否能夠直接經過Visual Studio界面完成IIS發佈。

在ASP.NET Core Web項目中建立「手動概要」:

  • 建立文件夾\Properties\PublishProfiles
  • 建立文件<MyProfile>.pubxml
你能夠從非ASP.NET Core項目中拷貝一個已有的.pubxml文件。下面是IIS下的概要文件例子:
 
 1 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 2   <PropertyGroup>
 3     <WebPublishMethod>MSDeploy</WebPublishMethod>
 4     <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
 5     <LastUsedPlatform>Any CPU</LastUsedPlatform>
 6     <SiteUrlToLaunchAfterPublish>http://samples.west-wind.com/AlbumViewerCore/index.html</SiteUrlToLaunchAfterPublish>
 7     <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
 8     <ExcludeApp_Data>False</ExcludeApp_Data>
 9     <PublishFramework>netcoreapp1.0</PublishFramework>
10     <UsePowerShell>True</UsePowerShell>
11     <EnableMSDeployAppOffline>True</EnableMSDeployAppOffline>
12     <MSDeployServiceURL>https://publish.west-wind.com</MSDeployServiceURL>
13     <DeployIisAppPath>samples site/albumviewercore</DeployIisAppPath>
14     <RemoteSitePhysicalPath />
15     <SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
16     <MSDeployPublishMethod>RemoteAgent</MSDeployPublishMethod>
17     <EnableMSDeployBackup>False</EnableMSDeployBackup>
18     <UserName>username</UserName>
19     <_SavePWD>True</_SavePWD>
20     <ADUsesOwinOrOpenIdConnect>False</ADUsesOwinOrOpenIdConnect>
21     <AuthType>NTLM</AuthType>
22   </PropertyGroup>
23 </Project>

 

AuthType NTLM修正

注意文件底部的<AuthType>NTLM</AuthType>鍵。此鍵很是重要,若是錯誤發佈操做將沒法執行。若是是從一個現有的文件拷貝過來的,請確保此鍵的設置。

當建立好.pubxml文件後,如今打開Visual Studio的發佈對話框,以下所示:
 
 

此時,你就能夠將網站發佈到遠程服務器上的IIS中,而且能夠增量更新內容。

這是目前爲止對IIS託管和發佈的總結,尚未文檔描述這些,整個發佈過程有些粗糙。顯然微軟知道這件事,也會在ASP.NET Core的RTM版本中修復。
相關文章
相關標籤/搜索