ASP.NET Core设计初衷是开源跨平台、高性能Web服务器,其中跨平台特性较早期ASP.NET是一个显著的飞跃,.NET现可以理直气壮与JAVA同台竞技,而ASP.NET Core的高性能特性更是成为致胜法宝。

ASP.NET Core 2.1+为IIS托管新增In-Process模型并作为默认选项(使用IISHttpServer替代了Kestrel,dotnet程序由IIS网站进程w3wp.exe内部托管)。

为了展示ASP.NET Core跨平台特性,本文还是重点着墨 经典的Out-Process托管模型。

宏观模型

为解耦平台差异,程序内置Http服务组件Kestrel,由平台web服务器转发请求到Kestrel。

  • 老牌web服务器定位成反向代理服务器,转发请求到ASP.Net Core程序(分别由IIS AspNetCore Module 和Nginx配置参数完成)

常规代理服务器,只用于代理内部主机对外网的连接需求,一般不支持外部对内部网络的访问请求;

当一个代理服务器能够代理外部网络的主机,访问内部网络,这种代理服务器被称为反向代理服务器 。

  • 平台web代理服务器、ASP.NET Core程序(dotnet.exe) 均为独立进程,平台自行决定互动细节,只需确保平台web服务器与Kestrel形成Http通信。

Kestrel

与老牌web服务器解耦,实现跨平台部署,要注意

  • 进程内Http服务器,ASP.NET Core具备了基本web服务器的能力,在内网部署和开发环境完全可使用dotnet.exe自宿模式运行。
  • Kestrel定位是Http服务组件,实力还比不上老牌web服务器,在timeout机制、web缓存、响应压缩等不占优势,在安全性等方面还有缺陷。

因此在生产环境中必须使用老牌web服务器反向代理请求。

不同平台管控应用、转发请求

要实现企业级稳定部署:

*nix平台

将ASP.NET Core程序以dotnet.exe自宿模式运行,并配置为系统守护进程(管控应用),再由Nginx转发请求

以下使用systemd创建进程服务文件 /etc/systemd/system/kestrel-eqidproxyserver.service

[Unit]
Description=EqidProxyServer deploy on centos [Service]
WorkingDirectory=/var/www/eqidproxyserver/eqidproxyServer
ExecStart=/usr/bin/dotnet /var/www/eqidproxyserver/eqidproxyServer/EqidProxyServer.dll
Restart=always
# Restart service after seconds if the dotnet service crashes:
RestartSec=
TimeoutStopSec=
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false [Install]
WantedBy=multi-user.target
sudo systemctl enable kestrel-eqidproxyserver.service       // 启用服务

安装Nginx,并配置Nginx转发请求;

server {
listen ;
server_name default_website;
root /usr/share/nginx/html; # Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf; location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Windows平台

[ 管控应用、转发请求] 由ASP.NET Core Module(插入在IIS Pipeline中的原生组件,下面简称ACM)一手操办。

w3wp.exe、dotnet.exe的互动关系是通过父子进程维系的。下图脚本力证dotnet.exe进程是w3wp.exe创建出来的子进程:

正因为如此,ACM在创建子进程时能指定子进程环境变量,约定donet.exe接收(IIS转发的请求)的侦听端口。

实际上从源码看ACM为子进程设定三个重要的环境变量:

  • ASPNETCORE_PORT   约定 Kestrel将会在此端口上监听
  • ASPNETCORE_APPL_PATH
  • ASPNETCORE_TOKEN   约定 携带该Token的请求为合法的转发请求

与ACM夫唱妇随的是UseIISIntegration()扩展方法,完成如下工作:

① 启动Kestrel服务在http://localhost:{ASPNETCORE_PORT}上监听

② 根据 {ASPNETCORE_TOKEN} 检查请求是否来自ACM转发

ACM转发的请求,会携带名为MS-ASPNETCORE-TOKEN:******的Request Header,以便dotnet.exe对比研判。

③ 利用ForwardedHeaderMiddleware中间件保存原始请求信息

linux平台部署需要手动启用ForwardedHeader middleware

https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-3.1

源码快速验证:
namespace Microsoft.AspNetCore.Hosting
{
public static class WebHostBuilderIISExtensions
{
// These are defined as ASPNETCORE_ environment variables by IIS's AspNetCoreModule.
private static readonly string ServerPort = "PORT";
private static readonly string ServerPath = "APPL_PATH";
private static readonly string PairingToken = "TOKEN";
private static readonly string IISAuth = "IIS_HTTPAUTH";
private static readonly string IISWebSockets = "IIS_WEBSOCKETS_SUPPORTED"; /// <summary>
/// Configures the port and base path the server should listen on when running behind AspNetCoreModule.
/// The app will also be configured to capture startup errors.
public static IWebHostBuilder UseIISIntegration(this IWebHostBuilder hostBuilder)
{
var port = hostBuilder.GetSetting(ServerPort) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{ServerPort}");
var path = hostBuilder.GetSetting(ServerPath) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{ServerPath}");
var pairingToken = hostBuilder.GetSetting(PairingToken) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{PairingToken}");
var iisAuth = hostBuilder.GetSetting(IISAuth) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{IISAuth}");
var websocketsSupported = hostBuilder.GetSetting(IISWebSockets) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{IISWebSockets}"); bool isWebSocketsSupported;
if (!bool.TryParse(websocketsSupported, out isWebSocketsSupported))
{
// If the websocket support variable is not set, we will always fallback to assuming websockets are enabled.
isWebSocketsSupported = (Environment.OSVersion.Version >= new Version(, ));
} if (!string.IsNullOrEmpty(port) && !string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(pairingToken))
{
// Set flag to prevent double service configuration
hostBuilder.UseSetting(nameof(UseIISIntegration), true.ToString()); var enableAuth = false;
if (string.IsNullOrEmpty(iisAuth))
{
// back compat with older ANCM versions
enableAuth = true;
}
else
{
// Lightup a new ANCM variable that tells us if auth is enabled.
foreach (var authType in iisAuth.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
if (!string.Equals(authType, "anonymous", StringComparison.OrdinalIgnoreCase))
{
enableAuth = true;
break;
}
}
} var address = "http://127.0.0.1:" + port;
hostBuilder.CaptureStartupErrors(true);
hostBuilder.ConfigureServices(services =>
{
// Delay register the url so users don't accidentally overwrite it.
hostBuilder.UseSetting(WebHostDefaults.ServerUrlsKey, address);
hostBuilder.PreferHostingUrls(true);
services.AddSingleton<IServerIntegratedAuth>(_ => new ServerIntegratedAuth()
{
IsEnabled = enableAuth,
AuthenticationScheme = IISDefaults.AuthenticationScheme
});
services.AddSingleton<IStartupFilter>(new IISSetupFilter(pairingToken, new PathString(path), isWebSocketsSupported));
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
services.Configure<IISOptions>(options =>
{
options.ForwardWindowsAuthentication = enableAuth;
});
services.AddAuthenticationCore();
});
}
return hostBuilder;
}
}
}

总结, ASP.NET Core跨平台的核心在于 程序内置Kestrel HTTP通信组件解耦了差异, 各平台建立Http通信的细节各不相同。

That's All.  本文旨在从框架设计初衷、进程模型、组件交互原理给大家剖析出ASP.NET Core跨平台技术内幕,关键内容均给出源码链接。

+ 完整版本CentOS部署ASP.NET Core程序,请参考https://www.cnblogs.com/JulianHuang/p/10455644.html

深入剖析ASP.NET Core2.1部署模型,你会大吃一惊的更多相关文章

  1. asp.net core2.1 部署centos7/linux系统 -- 安装部署(一)

    原文:asp.net core2.1 部署centos7/linux系统 -- 安装部署(一) 1.安装dotnet sdk(添加产品秘钥与yum源) 添加yum源:sudo rpm -Uvh htt ...

  2. asp.net core2.0 部署centos7/linux系统 --守护进程supervisor(二)

    原文:asp.net core2.0 部署centos7/linux系统 --守护进程supervisor(二) 续上一篇文章:asp.net core2.0 部署centos7/linux系统 -- ...

  3. 将asp.net core2.0项目部署在IIS上运行

    原文:将asp.net core2.0项目部署在IIS上运行 前言:  与ASP.NET时代不同,ASP.NET Core不再是由IIS工作进程(w3wp.exe)托管,而是独立运行的.它独立运行在控 ...

  4. 你真的了解ASP.NET Core 部署模型吗?

    ----------------------------   以下内容针对 ASP.NET Core2.1,2.2出现IIS进程内寄宿 暂不展开讨论-------------------------- ...

  5. 深度理解IIS下部署ASP.NET Core2.1 Web应用拓扑图

    原文:深度理解IIS下部署ASP.NET Core2.1 Web应用拓扑图 IIS部署ASP.NET Core2.1 应用拓扑图 我们看到相比Asp.Net, 出现了3个新的组件:ASP.NET Co ...

  6. 剖析Asp.Net Web API路由系统---WebHost部署方式

    上一篇我们剖析了Asp.Net路由系统,今天我们再来简单剖析一下Asp.Net Web API以WebHost方式部署时,Asp.Net Web API的路由系统内部是怎样实现的.还是以一个简单实例开 ...

  7. 【3】Asp.Net Core2.2新版管道处理模型

    [前言] 上一篇完成了Asp.Net Core 2.2项目的一个最简单功能的添加,从控制器-视图-实体轻松交互了一下,感觉跟之前的MVC没啥差别!但这些都是在组件封装的基础上完成的,在Core里面,其 ...

  8. 在阿里云Windows Server 上部署ASP .NET CORE2.0项目

    近期使用ASP.NET Core2.0对博客进行了重写,在部署到服务器时遇到了一些问题,来记录一下留用. 配置环境 安装 .Net Framework3.5 在IIS管理器上直接开启,这里总是失败,上 ...

  9. 一步一步带你做WebApi迁移ASP.NET Core2.0

    随着ASP.NET Core 2.0发布之后,原先运行在Windows IIS中的ASP.NET WebApi站点,就可以跨平台运行在Linux中.我们有必要先说一下ASP.NET Core. ASP ...

随机推荐

  1. 《Linux 鸟哥私房菜》 第一部分 Linux文件、目录与磁盘格式

    1.Linux就是内核层与系统调用接口层这2层.

  2. IIS7:通过脚本来配置ftp站点

    Appcmd.exe是IIS7提供的一个管理站点的命令行工具,同时支持Ftp和Http的站点,功能还算强大,具体使用方法参考微软网站. 需求 我这里的例子主要配置一个Ftp站点,并且允许CcUser这 ...

  3. fusioncharts 用法实例

    支持xml格式和json格式的数据. 用法很简单. 1.需要引入FusionCharts.js. 2.html中定义个id="chart"的div <div id=" ...

  4. mongo简介

    MongoDB MongoDB是一款强大.灵活.且易于扩展的通用型数据库 MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服 ...

  5. UVA - 10305 【全排列】

    题意 要求给出一组 包含 1 - N 的数字的序列 要求这个序列 满足 题给的限制条件 比如 1 2 就是 1 一定要在 2 前面 思路 因为 数据规模较小 可以用 全排列 然后判断每个序列 是否满足 ...

  6. Python网络编程--Echo服务

    Python网络编程--Echo服务 学习网络编程必须要练习的三个小项目就是Echo服务,Chat服务和Proxy服务.在接下来的几篇文章会详细介绍. 今天就来介绍Echo服务,Echo服务是最基本的 ...

  7. tkinter之button

    Button按钮,直接上代码: from tkinter import * def gs(): global read s=Label(read,text='昨夜西风凋敝树,堵上高楼,望尽天涯路!', ...

  8. HihoCoder1333 :平衡树(splay+lazy)(区间加值,区间删除)

    描述 小Ho:好麻烦啊~~~~~ 小Hi:小Ho你在干嘛呢? 小Ho:我在干活啊!前几天老师让我帮忙管理一下团队的人员,但是感觉好难啊. 小Hi:说来听听? 小Ho:事情是这样的.我们有一个运动同好会 ...

  9. BZOJ_5359_[Lydsy1805月赛]寻宝游戏_DP

    BZOJ5359_[Lydsy1805月赛]寻宝游戏_DP Description begin.lydsy.com/JudgeOnline/upload/201805.pdf 我们需要找到一条权值最大 ...

  10. ACM学习历程—HDU4956 Poor Hanamichi(模拟)

    Poor Hanamichi Problem Description Hanamichi is taking part in a programming contest, and he is assi ...