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. 解决Ubuntu(乌班图)vi/vim模式下粘贴的代码内容会多出的空格的问题

    vi/vim模式下的粘贴 因为linux系统和win系统的差异性,有时候在win环境运行的python代码会放在Linux系统上执行,这个时候就需要把win系统上IDE上的代码copy下来,在Linu ...

  2. 提高iOS开发效率的第三方框架等--不断更新中。。。

    1. Mantle Mantle 让我们能简化 Cocoa 和 Cocoa Touch 应用的 model 层.简单点说,程序中经常要进行网络请求,请求到得一般是 json 字符串,我们一般会建一个 ...

  3. spring-boot3代码

    App.java package com.kfit; import org.springframework.boot.SpringApplication; import org.springframe ...

  4. Canvas动画按钮

    在线演示 本地下载

  5. CSS那个背景图片的坐标怎么设置?怎么计算的?

    background:url(images/hh.gif) no-repeat -10px 0;},作用是移动背景的位置. 背影图片的左上角相对当前元素左上角的坐标. 右为X轴正半轴, 下为Y轴正半轴 ...

  6. 解决使用mybatis做批量操作时发生的异常:Parameter '__frch_item_0' not found. Available parameters are [list] 记录

    本文主要描述 使用mybatis进行批量更新.批量插入 过程中遇到的异常及总结: 首先贴出使用批量操作报的异常信息: java.lang.RuntimeException: org.mybatis.s ...

  7. SPOJ - GSS1 —— 线段树 (结点信息合并)

    题目链接:https://vjudge.net/problem/SPOJ-GSS1 GSS1 - Can you answer these queries I #tree You are given ...

  8. UVA 111 简单DP 但是有坑

    题目传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18201 其实是一道不算难的DP,但是搞了好久,才发现原来是题目没 ...

  9. 查 101.201.62.30 IP信誉方法

    查 101.201.62.30 IP信誉方法https://www.virustotal.com/#/ip-address/101.201.62.30https://talosintelligence ...

  10. Java常用类Date、Calendar、SimpleDateFormat详解

    Date类 java.util 包提供了 Date 类来封装当前的日期和时间,Date 类提供两个构造函数来实例化 Date 对象 第一个构造函数使用当前日期和时间来初始化对象   Date( ) 第 ...