ASP.NET Core的Kestrel和托管模式

上一篇中,我们简单使用.NET Core输出Hello World。今天我们继续ASP.NET Core的梳理——Kestrel Web服务器及托管模式。本篇的目标如下:

  • Kestrel介绍
    • 什么是Kestrel
    • 为什么要使用Kestrel
    • kerstrel的运行方式
  • IIS托管模式
    • 进程内托管
    • 进程外托管
  • 实例
  • 托管模式的选择

一、Kestrel介绍

  1. 什么是KestrelKestrel是Asp.Net Core应用程序默认的Web服务器。Asp.Net Core应用程序将Kestrel Web服务作为进程内服务器来处理web请求。它有以下几个特点:(1)多个应用程序不支持同一个端口号(2)跨平台,可在windows,linux,mac中运行(3)支持ssl,即HTTPS
  2. 为什么要使用KestrelIIS的功能已经很丰富,为什么Asp.Net Core确选择用Kestrel Web服务器?因为跨平台啊!!!IIS虽然具有丰富的功能,但也仅是支持windows的web服务器。如果要在其他跨平台Web服务器(例如Nginx,Apache)上运行Asp.Net Core应用程序,Asp.Net Core应用程序需要为每个Web服务器配置相应的启动机制。Kestrel Web服务器提供跨平台支持,选择用Kestrel Web服务器用作进程内服务器使得该应用程序具有相同且一致的启动进程。
  3. Kestrel的运行方式(1)单独运行Kestrel本身作为内部Web服务器,启动Asp.Net Core后,可以直接处理来自Internet的请求。如下图:图片(2)反射代理搭配IIS,Nginx或Apace,将收到的请求通过反射代理转发给Kestrel。
    图片

二、IIS托管模式

我们前面介绍了Asp.Net Core是有自己的托管Web服务器,使用自托管服务器实例可以在内部处理请求,这样就不需要IIS来运行,那为什么还需要IIS呢?原因是kestrel只是边缘的web服务,不支持完整服务器的所有功能,且不支持80/443端口的转发,所以IIS(或其它反射代理)仍是服务器的重要组成部分。那IIS(或其它反射代理)与Kestrel是如何有效的配合工作的?我们将它们的配合方式称为托管,它有两种托管方式:进程内托管和进程外托管。下面分别介绍这两种托管方式:

  1. 进程内托管进程内托管是在IIS工作进程(w3wp.exe)内托管Asp.Net Core应用程序。在IIS进程内就相当于放弃使用Kestrel,而是使用IIS应用程序池内部托管的新Web服务器实现(IISHttpServer),此实现访问本机IIS对象以创建HttpContext所需的请求数据,该数据将传递到ASP.NET Core中间件管道。承载ASP.NET Core模块的应用程序池不必运行.NET,因为该模块挂接到本机代码IIS管道中,所以Asp.Net Core应用程序部署在IIS的进程名称为w3wp。服务器接收到请求后的处理步骤如下图:
    图片
  2. 进程外托管在Asp.Net Core 2.2之前,IIS托管Asp.Net Core应用程序的唯一方法就是进程外,也叫代理模式托管,IIS在这充当服务器前端代理的角色,将请求传递到Kestrel内部服务器。每个请求首先到达IIS,AspNetCoreModule打包所有请求标头和数据,并将其从端口80/443(或任何端口)转发到Kestrel正在侦听的专用端口。因此Asp.Net Core应用程序部署在IIS的进程名称为dotnet。如下图:图片

三、实例

我们的实例将继续使用上一篇创建的默认程序,不过我们在此先稍作修改,将Startup类的Configure方法里的代码注释掉,替换成如下:app.Run(async context =>
          {
               await context.Response.WriteAsync($”Current Process Name:{System.Diagnostics.Process.GetCurrentProcess().ProcessName}”);
          });

  1. 进程内托管模式Asp.Net Core 应用默认为进程内托管模型。接下我们来看下Asp.Net Core分别在IIS和IISExpress运行的结果有什么不一样。(1)IISExpress我们从vs运行应用程序,在浏览器中显示消息,此时显示的进程名称就是iisexpress,因为运行程序vs使用的是IISExpress。如下所示:
    图片
    (2)IIS要使用IIS,确保在本地安装了Internet Information Services(IIS)管理器。代码还是原先的代码,但是我们要先将代码发布一下,右击项目选择“发布”,在【选取发布目标】对话框中选择“文件夹”,然后点击“创建配置文件”,最后点击“发布”。接下来在IIS中新建网站,并将根目录指向上一步中的publish文件夹,此时进程名称为:w3wp。这就是默认的进程内托管模式。浏览网站可以看到:图片
  2. 进程外托管模式(1)单独运行Kestrel本身作为内部Web服务器,启动Asp.Net Core后,可以直接处理来自Internet的请求。如下图:图片我们来看下它的实例。单独运行Kestrel可以使用.NET Core CLI运行。接下我们来看下操作步骤:a.打开运行窗口,输入cmd回车b.切换到项目存放路径,我这里是:E:WorkspaceFirstAppFirstWebAppc.输入donet run,运行成功显示如下:图片d.在浏览器输入http://localhost:5000,在浏览器中显示消息,此时显示的进程名称就是我们创建时的应用程序名称。如下所示:图片(2)反射代理搭配IIS,Nginx或Apace,将收到的请求通过反射代理转发给Kestrel。
    图片a.IISExpress       首先我们要更改下托管方式,更改步骤:右击项目选择“属性”,弹出如下图:图片
    然后从vs运行程序,此时显示的进程名称就是我们创建的应用程序名称,与单独运行时相同。浏览器输出结果如下:图片b.IIS使用IIS部署时,我们需改动一个地方,前一篇介绍过.csproj这个件,今天我们要使用这个文件来配置托管模式。右击项目选择“编辑项目文件”,在PropertyGroup这个节点下增加一个子节点:<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>结果如下图:图片修改完保存,重新发布一遍,发布完成后在浏览输出地址,此时的进程名称为:dotnet,这是进程外托管模式。显示结果如下图所示:图片

我们看下面的表格,进程内和进程外分别在IIS和IISExpress托管的进程名称。

IISIISExpress
进程内托管w3wpiisexpress
进程外托dotnet创建时的项目名称

注:进程外托管会多一个Kestrel运行的进程,它是通过初始Host来运行应用程序。

单独运行Asp.Net Core应用程序时使用的是Kestrel内部服务器,属于进程外托管模式,进程名称是我们创建时的应用程序名称。

四、托管模式的选择

那我们在创建的Asp.Net Core应用程序是选择进程内托管还是进程外?

对于部署在IIS的新应用程序,我想应该都会使用InProcess托管吧,因为它提供了更好的性能(可以使用工具进行压测[west wind websurge]),并且占用的资源较少,还避免了IIS和Kestrel之间的额外网络吞吐量,减少进程的维护。

当然,在某些情况下,可能需要使用OutOfProcess托管,例如用于故障排除和调试故障服务器(可以在启用控制台查看日志记录),或者在不同平台部署之间100%兼容,而Kestrel是用于处理所有平台上的HTTP请求的主要机制,选择OutOfProcess是最佳的。但是出于其它意图和目的,在IIS上运行InProcess是必经之路,除非有非常特定的需求要求使用Kestrel和OutOfProcess托管。

最后再啰嗦一句,在使用.NET Core CLI运行Asp.Net Core应用程序时,它会忽略您指定的托管设置,而使用进程外托管模式。

祝大家学习愉快!

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/218371.html

联系我们
联系我们
分享本页
返回顶部