ASP.NET Core跨平台技术内幕

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托管模型。

宏观设计

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

  • 老牌web服务器定位成反向代理服务器,转发请求到ASP.NET Core程序(分别由IIS ASP.NET Core Module和Nginx负责)

常规代理服务器,只用于代理内部主机对外网的连接需求,一般不支持外部对内部网络的访问请求; 当一个代理服务器能够代理外部网络的主机,访问内部网络,这种代理服务器被称为反向代理服务器 。

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

Kestrel

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

  • Kestrel使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 10 seconds if the dotnet service crashes:
RestartSec=10
TimeoutStopSec=90
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false[Install]
WantedBy=multi-user.target
// 启用服务,在localhost:5000端口侦听请求
sudo systemctl enable kestrel-eqidproxyserver.service   

安装Nginx,并配置Nginx转发请求到localhost:5000:

server {listen       80;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在创建dotnet.exe子进程时能指定环境变量,约定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(6, 2));}if (!string.IsNullOrEmpty(port) && !string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(pairingToken)){// Set flag to prevent double service configurationhostBuilder.UseSetting(nameof(UseIISIntegration), true.ToString());var enableAuth = false;if (string.IsNullOrEmpty(iisAuth)){// back compat with older ANCM versionsenableAuth = 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通信组件,解耦web服务器差异;依平台特性约定Http通信细节。

本文从框架设计初衷、进程模型、组件交互验证我对ASP.NET Core跨平台特性的理解。

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

往期精选

AspNetCore结合Redis实践消息队列

TPL Dataflow组件应对高并发,低延迟要求

AspNetCore应用注意这一点,CTO会对你刮目相看

实例解读Docker Swarm

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Visual Studio Code 进行远程开发

在完成了 AT 指令入门的学习之后&#xff0c;接下来就要使用 AT 指令进行 Socket 通信了。问题在于&#xff0c;之前 .NET 的 Socket 编程只需一台电脑便可进行学习&#xff0c;服务器和客户端都可以在本机运行&#xff0c;也可以分别运行在局域网上的两台电脑之上。而 NB-IOT …

.NETCore3.1中的Json互操作最全解读-收藏级

前言本文比较长&#xff0c;我建议大家先点赞、收藏后慢慢阅读&#xff0c;点赞再看&#xff0c;形成习惯&#xff01;我很高兴,.NETCore终于来到了3.1LTS版本&#xff0c;并且将支持3年&#xff0c;我们也准备让部分业务迁移到3.1上面&#xff0c;不过很快我们就遇到了新的问题…

逻辑结构的四种基本关系

逻辑结构的四种基本关系 1集合结构&#xff1a;数据元素之间除了“属于同一集合”的关系外&#xff0c;没有其他关系 2线性结构&#xff1a;数据元素之间存在一对一的关系 3树结构&#xff1a;数据元素之间存在一对多的关系 4图结构&#xff1a;数据元素之间存在多对多的关系

轻量级开源小程序SDK发车啦

Magicodes.WxMiniProgram.Sdk轻量级微信小程序SDK&#xff0c;支持.NET Framework以及.NET Core。目前已提供Abp模块的封装&#xff0c;支持开箱即用。地址&#xff1a;https://github.com/xin-lai/Magicodes.WxMiniProgram.SdkNuget新的包主要功能轻量级微信小程序SDK&#xf…

考察对顺序表的理解

顺序表是在计算机内存中以数组的形式保存的线性表 线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中&#xff0c;即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻…

2020年你应该学习 .Net Core

一、什么是.NET Core.NET Core是一个开源通用的开发框架&#xff0c;支持跨平台&#xff0c;即支持在Window&#xff0c;macOS&#xff0c;Linux等系统上的开发和部署&#xff0c;并且可以在硬件设备&#xff0c;云服务&#xff0c;和嵌入式/物联网方案中进行使用。.NET Core的…

对表头指针、表头结点,单链表删除的理解

https://blog.csdn.net/weixin_46678290/article/details/105309156

C# WPF发票打印

C# WPF发票打印内容目录实现效果业务场景编码实现本文参考源码下载1.实现效果发票界面PDF打印结果2.业务场景界面作为发票预览&#xff0c;按客户需求可打印成发票纸张给客户。3.编码实现3.1 添加Nuget库站长使用 .Net Core 3.1 创建的WPF工程&#xff0c;创建“Invoice”解决方…

dotNET知音,19年归档

2019年下半年开通公众号&#xff0c;尝试着分享和技术交流&#xff0c;也很高兴认识很多NETer同行。为了方便阅读&#xff0c;进行归档&#xff0c;如果之前有错过的文章&#xff0c;这是一个很好的补课机会。.NETCore3.0&#xff1a;《.Net Core3.0 配置Configuration》《.Net…

阿里如何应对亿级高并发大流量?如何保障高可用和稳定性!

作者&#xff1a;丁浪&#xff0c;目前在创业公司担任高级技术架构师。曾就职于阿里巴巴大文娱和蚂蚁金服。具有丰富的稳定性保障&#xff0c;全链路性能优化的经验。架构师社区特邀嘉宾&#xff01;阅读本文&#xff0c;你将会收获&#xff1a; 高并发、大流量场景的常见问题和…

动手造轮子:写一个日志框架

动手造轮子&#xff1a;写一个日志框架Intro日志框架有很多&#xff0c;比如 log4net / nlog / serilog / microsoft.extensions.logging 等&#xff0c;如何在切换日志框架的时候做到不用修改代码&#xff0c;只需要切换不同的 loggingProvider 就可以了&#xff0c;最低成本的…

【C】@程序员,我们送给你一个成熟的Excel导入导出组件

程序员的显著特点有一天跟一位同事跟我闲聊&#xff0c;讨论起过去若干年软件行业的感受&#xff0c;他问了个问题&#xff1a;你觉得一个好的软件工程师最显著的特点是什么&#xff1f;我想了一会&#xff0c;说&#xff1a;大概是坐得住吧。某种意义上来说&#xff0c;在互联…

SummerBoot,将SpringBoot的先进理念与C#的简洁优雅合二为一

哈哈哈哈&#xff0c;大家好&#xff0c;我就是高产似母猪的三合&#xff0c;好久没写博客了&#xff0c;因为最近几个月在不断的加班&#xff0c;加班时长平均每个月120小时以上。今天是2020年的第一天&#xff0c;作为一条程序汪&#xff0c;觉得不做点啥好像对不起这个特别有…

C#刷遍Leetcode面试题系列连载(6):No.372 - 超级次方

点击蓝字“dotNET匠人”关注我哟加个“星标★”&#xff0c;每日 7:15&#xff0c;好文必达&#xff01;前文传送门:C# 刷遍 Leetcode 面试题系列连载&#xff08;1&#xff09; - 入门与工具简介C#刷遍Leetcode面试题系列连载&#xff08;2&#xff09;: No.38 - 报数C#刷遍Le…

使用 Postman 测试你的 API

使用 Postman 测试你的 APIIntro最近想对 API 做一些自动化测试&#xff0c;看了几个工具&#xff0c;最后选择了 postman&#xff0c;感觉 postman 的设计更好一些&#xff0c;我们可以在请求发送之前和请求获取到响应之后都可以自定义脚本&#xff0c;很灵活。而且 postman 的…

使用 postman 给 API 写测试

使用 postman 给 API 写测试Intro上次我们简单介绍了 使用 postman 测试 API&#xff0c;这次主要来写一些测试用例以检查请求的响应是否符合我们的预期以及如何使用脚本测试使用 postman 内置的随机变量postman 内置的有一些产生随机值的变量&#xff0c;在发送请求时随机生成…

ASP.NETCore编程实现基本认证

HTTP基本认证在HTTP中&#xff0c;HTTP基本认证&#xff08;Basic Authentication&#xff09;是一种允许浏览器或其他客户端程序使用&#xff08;用户名&#xff0c;口令&#xff09;请求资源的身份验证方式&#xff0c;不要求cookie,session identifier、login page等标记或载…

计算机原理(计算机系统漫游)

计算机五大组成部件&#xff1a;运算器&#xff08;ALU&#xff09;&#xff0c;控制器&#xff0c;存储器&#xff0c;输入部件&#xff0c;输出部件 1.控制器 2.运算器 逻辑运算&#xff08;判断事物的对与错&#xff09; 数学运算(11) 控制器运算器中央处理器&#xff08;CP…

使用ASP.NET Core 3.x 构建 RESTful API - 4.2 过滤和搜索

向Web API传递参数数据可以通过多种方式来传给API。 Binding Source Attributes 会告诉 Model 的绑定引擎从哪里找到绑定源。 共有以下六种 Binding Source Attributes&#xff1a; [FromBody] 请求的 Body [FromForm] 请求的 Body 中的 form数据 [FromHeader] 请求的 Header […