您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

ASP.NET Core跨平台技术内幕

时间:2020-01-06 11:31:19  来源:  作者:

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。

ASP.NET Core跨平台技术内幕
  • 老牌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服务器反向代理请求。

跨平台管控程序,转发请求

要实现企业级稳定部署:

ASP.NET Core跨平台技术内幕

*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/eqidproxyServerExecStart=/usr/bin/dotnet /var/www/eqidproxyserver/eqidproxyServer/EqidProxyServer.dllRestart=always# Restart service after 10 seconds if the dotnet service crashes:RestartSec=10TimeoutStopSec=90KillSignal=SIGINTSyslogIdentifier=dotnet-exampleUser=rootEnvironment=ASPNETCORE_ENVIRONMENT=ProductionEnvironment=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创建出来的子进程:

ASP.NET Core跨平台技术内幕

得益此关系,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.IsOrEmpty(port) && !string.IsOrEmpty(path) && !string.IsOrEmpty(pairingToken)) { // Set flag to prevent double service configuration hostBuilder.UseSetting(nameof(UseIISIntegration), true.ToString);
 var enableAuth = false; if (string.IsOrEmpty(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通信组件,解耦web服务器差异;依平台特性约定Http通信细节。

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

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



Tags:ASP.NET   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
Asp.Net Core Identity 是.Net自带的身份认证系统,支持用户界面 (UI) 登录功能,并且管理用户、密码、配置文件数据、角色、声明、令牌、电子邮件确认等等。使用Visual Studio...【详细内容】
2022-06-05  Tags: ASP.NET  点击:(35)  评论:(0)  加入收藏
前几天有个老项目找到我,有多老呢?比我工作年限都长,见到这个项目我还得叫一声前辈。这个项目目前使用非常稳定,十多年了没怎么更新过,现在客户想加一个小功能:在线预览Word文档。...【详细内容】
2022-04-27  Tags: ASP.NET  点击:(65)  评论:(0)  加入收藏
之前,我们已经了解了ASP.NET Core中的身份认证,现在,我们来聊一下授权。老规矩,示例程序源码XXTk.Auth.Samples已经提交了,需要的请自取。概述ASP.NET Core中的授权方式有很多,我...【详细内容】
2022-04-20  Tags: ASP.NET  点击:(143)  评论:(0)  加入收藏
序言本文将分别介绍 Authentication(认证) 和 Authorization(授权)。并以简单的例子在 ASP.NET Core 6.0 的 WebAPI 中分别实现这两个功能。 相关名词Authentication 和 Author...【详细内容】
2022-04-18  Tags: ASP.NET  点击:(197)  评论:(0)  加入收藏
中间件是一种装配到应用管道以处理请求和响应的软件。 ASP.NET Core 提供了一组丰富的内置中间件组件,但在某些情况下,你可能需要写入自定义中间件。备注本主题介绍如何编写基...【详细内容】
2021-12-17  Tags: ASP.NET  点击:(128)  评论:(0)  加入收藏
直奔主题,今天我要给大家分享的基于ASP.NETCore开源二次开发框架就是YiShaAdmin。YiShaAdmin 是一款基于.NET Core Web + Bootstrap的企业级快速后台开发框架。内置模块如:用...【详细内容】
2021-07-19  Tags: ASP.NET  点击:(303)  评论:(0)  加入收藏
原文:bit.ly/3wFqDy9 作者:Daniel 译者:王亮.NET 6 预览版 4 现已发布,其中包括对 ASP.NET Core 的许多新改进。下面是此次预览版中 ASP.NET Core 的更新内容: 引入最小 API 异步...【详细内容】
2021-05-27  Tags: ASP.NET  点击:(355)  评论:(0)  加入收藏
asp.net core mvc 对应着 .NET Framework 中的 ASP.NET MVC, 前者可以跨平台,可扩展,高性能,不过令人惊讶的是,虽然 ASP.NET Core 提供了大量的可选项可以完美的处理 404 错误,但...【详细内容】
2020-12-24  Tags: ASP.NET  点击:(203)  评论:(0)  加入收藏
我们经常使用的各类网站和App均会涉及注册、登录和修改密码等功能,登录系统后,有些功能会提示没有权限,甚至有些位置我们无法访问,这些都是系统权限和认证的体现。我们从本章及...【详细内容】
2020-11-10  Tags: ASP.NET  点击:(102)  评论:(0)  加入收藏
0. 前言这一篇我们将介绍一下.net core 的加密和解密。在Web应用程序中,用户的密码会使用MD5值作为密码数据存储起来。而在其他的情况下,也会使用加密和解密的功能。常见的加...【详细内容】
2020-06-22  Tags: ASP.NET  点击:(71)  评论:(0)  加入收藏
▌简易百科推荐
在本文中,我们将学习如何使用 Next.js、 Prisma、 Postgres 和 Fastify 构建一个 Full-stack 应用程序。在本文中,我们将学习如何使用 Next.js、 Prisma、 Postgres 和 Fastif...【详细内容】
2022-07-12  qaseven    Tags:全栈   点击:(9)  评论:(0)  加入收藏
好的软件开发网站有哪些?做软件开发哪些网站能提供帮助呢?这些很多做软件开发的小伙伴都会问到的问题。007出海全球社交流量导航网站,整合了多方出海跨境网站资源,为你介绍出海...【详细内容】
2022-07-08  Chuhai007    Tags:软件开发   点击:(10)  评论:(0)  加入收藏
我们用monkey做压力测试后,会保存一个monkey日志,那如果想快速的分析日志中有哪些异常,我们可以用批处理工具进行快速的筛查,我们一起来看看吧。先编写个小脚本,然后修改为bat后...【详细内容】
2022-07-08  溪流涌动    Tags:monkey   点击:(13)  评论:(0)  加入收藏
白盒测试落地实践分为两个大方向,一个是静态分析,一个是动态分析,当然啦,也可以叫做静态测试和动态测试。那我们如何高质量保效率的做好白盒测试呢?Parasoft已经为您准备好了成熟...【详细内容】
2022-07-08  Parasoft中国    Tags:白盒测试   点击:(11)  评论:(0)  加入收藏
Altium Designer 自带脚本功能的开发项目,可以调用官方AD API接口对原理图或者PCB进行自动操作,本文主要分享开发的流程,和一些基本的概念信息,本文介绍的脚本工具例子可以用在P...【详细内容】
2022-07-07  电子工程师伟哥    Tags:Altium Designer   点击:(21)  评论:(0)  加入收藏
一、目录介绍 前置知识点 NIO Netty 的核心组件 Channel Callback Future 和 Promise 事件和 ChannelHandler Hello World二、前置知识点1、NIO首先我们需要回顾一...【详细内容】
2022-07-06  架构师jickly    Tags:聊天系统   点击:(16)  评论:(0)  加入收藏
1.事件流事件流是对事件执行过程的描述,了解事件的执行过程有助于加深对事件的理解,提升开发实践中对事件运用的灵活度。2.捕获和冒泡捕获阶段是【从父到子】的传导过程,冒泡阶...【详细内容】
2022-07-06  金乾坤    Tags:API   点击:(13)  评论:(0)  加入收藏
刷盘策略CommitLog的asyncPutMessage方法中可以看到在写入消息之后,调用了submitFlushRequest方法执行刷盘策略:public class CommitLog { public CompletableFuture<PutMe...【详细内容】
2022-07-06  Java码农之路    Tags:RocketMQ   点击:(16)  评论:(0)  加入收藏
最近读了本好书-《深度学习推荐系统》,读完不觉全身通畅,于是就有了写这篇文章的想法,把自己的理解和总结分享给大家。 本文将按照从算法到工程的顺序,先介绍一下推荐系统整体...【详细内容】
2022-07-05  InfoQ    Tags:推荐系统   点击:(22)  评论:(0)  加入收藏
在后端并不是写完一个接口的业务逻辑就能投入使用的,接口的优化更是一个难点与麻烦之处(下面的内容我们不考虑前端的处理,因为不能完全靠前端,前后端都需要做自己的处理工作)1.幂...【详细内容】
2022-07-05  老诚不bug  掘金  Tags:幂等   点击:(20)  评论:(0)  加入收藏
相关文章
站内最新
站内热门
站内头条