随笔 - 290  文章 - 10  评论 - 85  2

原文链接: https://weblog.west-wind.com/posts/2019/Mar/16/ASPNET-Core-Hosting-on-IIS-with-ASPNET-Core-22

 

ASP.NET Core 2.2已经出现了一段时间,如果您计划在IIS中托管,它会对托管模型进行一些重大改进。在以前的版本中,您需要通过将来自IIS的请求代理到ASP.NET Core Kestrel服务器来托管ASP.NET Core应用程序,其中IIS有效地作为反向代理。

在2.2版中,ASP.NET Core增加了对直接进程内托管的支持,使用一种允许在进程内和进程外托管之间切换的简单机制,大大提高了吞吐量。

在这篇文章中,我将重点关注新的In Process托管模型,因为这是改变和改进的,但我会在这里回顾这两个模型的基础知识,所以这篇文章可以独立存在。我将从改变后的内容开始,然后深入研究模型的工作原理以及它们的区别。

 

ASP.NET Core 2.2在IIS上添加了InProcess Hosting


ASP.NET Core的原始版本要求您使用通过IIS代理的Out of Process模型在IIS上进行托管。请求命中IIS并转发到运行Kestrel Web Server的ASP.NET Core应用程序。

Out of Process Hosting(pre v2.2 model)

IIS Out of Process Hosting

IIS Out of Process Hosting

图1 - Out of Process Hosting使用IIS作为代理将请求转发到dotnet.exe托管的控制台应用程序。

使用ASP.NET Core 2.2,IIS上现在有一个In Process托管模型,它直接在IIS应用程序池中托管ASP.NET Core,而无需代理运行.NET Core本机Kestrel Web Server的外部dotnet.exe实例。

在Process Hosting中(v2.2及更高版本)

 

图2 - 使用In Process托管您的应用程序运行IIS应用程序池的nside并使用IIS的内部处理管道。

In Process模型不使用Kestrel,而是使用直接托管在IIS应用程序池中的新Web服务器实现(IISHttpServer),这种方式与传统ASP.NET连接到IIS的方式类似。

此实现访问本机IIS对象以构建创建HttpContext所需的请求数据,该HttpContext将传递到ASP.NET Core中间件管道。与旧版本一样,承载ASP.NET核心模块的应用程序池不必运行.NET,因为模块挂接到本机代码IIS管道。

虽然这听起来像是一个相当剧烈的变化,但从应用程序兼容性方面来看,除了更快的请求吞吐量之外,我还没有遇到任何对我的应用程序产生任何影响的问题。

此功能显着提高了IIS上的ASP.NET Core请求的吞吐量。在我的袖口测试中,我看到使用IIS InProcess托管的小型,无需任何请求的吞吐量超过两倍。稍后会详细介绍。

Microsoft在引入此托管模型方面做得非常出色,对现有配置的影响最小:通过传播到已部署的web.config文件中的简单项目配置开关,可以轻松地在旧的OutOfProcess和InProcess模型之间切换。

OutOfProcess还是InProcess?使用InProcess
对于部署到IIS的新应用程序,您几乎肯定会希望使用InProcess托管,因为它提供了更好的性能,并且通常资源消耗较少,因为它避免了IIS和Kestrel之间的额外网络跳跃,并在需要的机器上维护额外的进程受到监控。

在某些情况下,可能需要OutOfProcess托管,例如故障排除和调试故障服务器(例如,您可以在启用控制台日志记录的情况下运行),或者如果您希望在同一应用程序的不同部署之间实现100%兼容,无论是在Windows还是Linux上,因为Kestrel是用于在所有平台上处理HTTP请求的主要机制。使用InProcess模型,您不使用Kestrel,而是直接与IIS的请求管道接口的自定义IISHttpServer实现。

但是对于大多数意图和目的,我认为在IIS上运行InProcess是可行的方法,除非您非常具体地需要Kestrel和OutOfProcess托管。

新的ASP.NET Core项目自动为InProcess托管配置项目,但如果您来自较旧的项目,则可能必须明确更新项目设置。

受影响的设置
在托管模式之间切换非常简单,只需要在.csproj文件内或web.config中进行配置切换。

项目变更 - <AspnetCoreHostingModel>
第一个更改是在项目文件中,您可以使用<AspNetCoreHostingModel>键指定托管模型。

要使用InProcess宿主,请将以下内容添加到Web项目的.csproj文件中:

<PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

相关的项目设置是AspNetCoreHostingModel,它可以是InProcess或OutOfProcess。 当缺少它时,默认使用旧的OutOfProcess模式,该模式使用外部Kestrel服务器,IIS充当代理。

这会影响发布项目时dotnet发布创建配置的方式以及在项目发布时将其生成到web.config文件中的内容。

web.config更改
<AspnetCoreHostingModel>项目设置通过将配置数据写入项目的web.config文件来影响生成的构建输出。 具体来说,它在生成的<aspNetCore>元素上设置hostingModel属性:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" />
      </handlers>
      
      <!-- hostingModel is the new property here -->
      <aspNetCore processPath="dotnet" arguments=".\WebApplication1.dll"    
                  stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout"
                  hostingModel="InProcess" />
                  
    </system.webServer>
  </location>
</configuration>

如果项目中的<AspNetCoreHostingModel>键设置为OutOfProcess或缺少,则不会生成hostingModel属性,并且应用程序默认为OutOfProcess。

 在“发布”上刷新web.config
我发现,与发布输出文件夹中的其他文件不同,web.config文件在新发布时未更新,除非我删除了文件(或整个发布文件夹)。如果您进行了影响IIS配置的更改,我建议您修改发布文件夹并执行干净发布。

请注意,只需更改“发布”文件夹中web.config中的InProcess和OutOfProcess之间的值,即可在发布后轻松切换模式。如果要在启用了详细日志设置的故障应用程序上记录输出,这对于调试很有用。

请记住,如果您更改发布输出,则下次再次发布时将覆盖该输出。

酷 - 这个单一设置就是你需要改变才能利用InProcess托管,你将获得一些连接到你的应用程序的额外速度。


要了解InProcess托管IIS是一项很好的改进,让我们回顾一下如何在带有IIS的Windows上托管ASP.NET Core应用程序。

什么是ASP.NET核心应用程序?
创建ASP.NET Core应用程序时,通常会创建一个使用dotnet。\ MyApplication.dll启动的独立控制台应用程序。运行控制台应用程序时,ASP.NET Core在应用程序内部托管其自己的内部Kestrel Web服务器。 Kestrel处理传入的HTTP流量,并将HttpContext的Kestrel连接器处理到ASP.NET Core请求中间件管道以进行处理。

在构建ASP.NET Web应用程序时,您实际上创建了一个完全独立的Web服务器,它在其上运行ASP.NET Core。

为什么我的Web服务器需要Web服务器?
对于在Windows上托管的实时应用程序,通常使用IIS作为ASP.NET Core应用程序的前端服务器,而不是直接访问运行.NET Kestrel Web Server的ASP.NET Core。

简而言之,ASP.NET核心中内置的Kestrel Web服务器并不是面向Internet的Web服务器,而是充当应用程序服务器或边缘服务器来处理非常具体的数据处理任务。 Kestrel针对应用场景进行了优化,但并未针对静态文件服务或管理服务器生命周期等其他事项进行优化

因此,您通常不希望直接在Web应用程序中运行Kestrel。在使用IIS的Windows上以及在Linux上您都倾向于使用Web服务器nginx或ha-proxy来处理非应用程序问题时也是如此。我写过如何设置IIS重写规则来路由常见的静态文件,而不是让Kestrel处理它们。这不仅仅是关于速度,它还可以让您的Web应用程序专注于执行它旨在执行的动态操作,让IIS完成它的设计工作。

以下是关于为什么要使用完整Web服务器而不是运行直接连接到Web的应用程序的许多争论:

端口共享
Kestrel当前不能像IIS和http.sys在Windows上那样进行端口共享。目前,仅Windows上的IIS支持该功能。 (AFAIK你甚至不能使用HttpSys服务器来做到这一点)。此外,尽管可以在ASP.NET Core中使用主机头路由,但目前设置它并不容易或难以维护。

终身管理
如果您在没有任何支持基础架构的情况下运行应用程序,任何崩溃或故障都将关闭应用程序并使您的站点脱机无论如何,您需要某种主机监视器,以确保您的应用程序在失败时继续运行,并且IIS提供了开箱即用的功能。具有ASP.NET核心模块的ASP.NET Core可以直接通过重新启动可在故障时重新启动应用程序的应用程序池而获益。

静态文件服务
Kestrel目前在静态文件处理方面不是很好,与IIS优化的静态文件缓存和压缩基础架构相比,Kestrel相当慢。 IIS充分利用内核模式缓存,并内置压缩基础结构,比现在的ASP.NET StaticFile处理程序(“.UseStaticFiles()”)更高效。

还有其他原因:安全性和服务器强化,管理功能,管理SSL证书,完整日志记录和Http请求跟踪工具等等。所有充分的理由都坐在专用的Web服务器平台上,而不是运行和管理自托管的服务器实例。

posted on 2019-07-05 11:53  Gu  阅读(...)  评论(...编辑  收藏