首页 > 代码库 > 在IIS上发布并运行ASP.NET Core
在IIS上发布并运行ASP.NET Core
在本篇文章中,你可以了解ASP.NET Core是如何运行在IIS上下文中的,怎样才能把ASP.NET Core应用程序发布在IIS上。
IIS和ASP.NET Core
关于ASP.NET Core,最重要的一点就是它托管于一个独立运行的控制台程序。它不用托管在IIS中,也不依赖IIS。ASP.NET Core应用程序有自托管的Web服务器,并且可以使用这个自托管的服务器实例在内部处理请求。
经典的ASP.NET托管
ASP.NET Core与IIS
ASP.NET Core则完全不同,它并不是运行在IIS的工作进程中,而是独立运行的。它运行于控制台应用程序之中,控制台中则运行了Kestrel Web服务器组件。Kestrel作为一款.NET Web服务器的实现,它在吞吐量性能方面做了很多工作。它可以快速将来自网络的请求接入到应用程序中,但是它仅仅是一个最基本的Web服务器。它没有类似IIS的Web管理服务,也没有IIS那么多的功能。
当选择在Windows平台上运行时,将IIS作为Kestrel的前置服务器可以获得额外一些基础功能。比如通过主机头的80/443端口转发、处理生命周期管理和证书管理等。
ASP.NET Core程序独立运行在控制台应用程序中,并通过dotnet运行时命令调用。它并没有被加载到IIS工作进程中,但是IIS却加载了名为AspNetCoreModule的本地Module,这个Module用于执行外部的控制台程序。
AspNetCoreModule是作为ASP.NET Core Server Hosting Bundle的一部分被安装在服务器上的。
AspNetCoreModule作为IIS本地Module,在IIS处理管道周期的最开始就能hook到请求,紧接着就将所有请求重定向到后端的ASP.NET Core程序。这里是所有的请求,也就是说即便是顶级的映射Handler,比如aspx。这些都将从IIS管道中分流到ASP.NET Core中处理。这意味着,没法简单的将ASP.NET Core和其他框架放在同一个站点(虚拟目录)中。这看起来有点退步了,因为在此之前可以混合使用不同框架。
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程序里。
Kestrel接收到请求,并将其推送到ASP.NET Core的中间件处理管道中,该处理管道稍后将处理这个请求并将请求传入到应用程序逻辑代码中。HTTP的输出结果会再次传回到IIS,接着IIS将结果通过Internet返回给初始化这个请求的客户端,它可能是浏览器、手机客户端或者一个应用程序。
AspNetCoreModule配置在位于应用程序根目录的web.config文件中。配置文件定义了用来加载.NET Core程序的启动命令(dotnet)和参数(应用程序主dll)。web.config文件中的配置标明了需要加载的应用程序模块和启动DLL的根目录。
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>
还需要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程序来处理。
不要把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”,这是因为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。
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网站发布。
特定版本的解决方法
很显然,这个问题在RC2之后的版本会得到更新。所以,当你在一个月后读到本文的这些步骤时,请先确认下是否可以直接通过Visual Studio界面完成IIS发布。
在ASP.NET Core Web项目中创建“手动概要”:
- 创建文件夹\Properties\PublishProfiles
- 创建文件<MyProfile>.pubxml
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>键。此键非常重要,如果错误发布操作将无法执行。如果是从一个现有的文件拷贝过来的,请确保此键的设置。
此时,你就可以将网站发布到远程服务器上的IIS中,并且可以增量更新内容。
在IIS上发布并运行ASP.NET Core