当前位置:首页 > 技术文章 > 正文内容

ASP.NET Core跨平台技术内幕(.net 跨平台gui)

arlanguage3个月前 (01-31)技术文章22

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/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创建出来的子进程:

得益此关系,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";
/// /// 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(_ => new ServerIntegratedAuth { IsEnabled = enableAuth, AuthenticationScheme = IISDefaults.AuthenticationScheme }); services.AddSingleton(new IISSetupFilter(pairingToken, new PathString(path), isWebSocketsSupported)); services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); services.Configure(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

让干货飞一会。

............

扫描二维码推送至手机访问。

版权声明:本文由AR编程网发布,如需转载请注明出处。

本文链接:http://www.arlanguage.com/post/1516.html

标签: nginx asp.net
分享给朋友:

“ASP.NET Core跨平台技术内幕(.net 跨平台gui)” 的相关文章

了解PHP-FPM

在服务器上,当我们查看php进程时,全都是php-fpm进程,大家都知道这个就是php的运行环境,那么,它到底是个什么东西呢?PHP-FPM简介PHP-FPM,就是PHP的FastCGI管理器,用于替换PHP FastCGI的大部分附加功能,在PHP5.3.3后已经成为了PHP的标配。有小伙伴要问了...

405状态码Nginx解决办法

最近由于业务系统并发量比较大,所以在已有负载均衡的基础上,我们做了Nginx动静分离,但是系统访问后报错,经过F12(浏览器开发者模式)和Nginx日志分析,发现请求状态变成了405,故百度解释如下:问题原因: 请求的方式(get、post、delete)方法与后台规定的方式不符合。比如: 后台方...

Linux 网络延迟排查方法 linux延迟10秒

在 Linux 服务器中,可以通过内核调优、DPDK 以及 XDP 等多种方式提高服务器的抗攻击能力,降低 DDoS 对正常服务的影响。在应用程序中,可以使用各级缓存、WAF、CDN 等来缓解 DDoS 对应用程序的影响。但是需要注意的是,如果 DDoS 流量已经到达 Linux 服务器,那么即使应...

一起学习Kubernetes:容器和镜像

简述容器每个运行的容器都是可重复的;包含依赖环境在内的标准,意味着无论你在哪里运行它都会得到相同的行为。容器将应用程序从底层的主机设施中解耦。 这使得在不同的云或 OS 环境中部署更加容易。Kubernetes 集群中的每个节点都会运行容器,这些容器构成分配给该节点的 Pod。 单个 Pod 中的容...

非常想学黑客技术,但是却又不知道如何入门?看这里就够了

黑客攻防是一个极具魅力的技术领域,但成为一名黑客毫无疑问也并不容易。你必须拥有对新技术的好奇心和积极的学习态度,具备很深的计算机系统、编程语言和操作系统知识,并乐意不断地去学习和进步。如果你想成为一名优秀的黑客,下面是12种最重要的基础条件,请认真阅读:第一点:了解黑客的思维方式我们生活中用到的网站...

终于有人把Docker讲清楚了,Docker入门教程,原来这么简单...

Docker是一个使用Go语言开发的开源的应用容器引擎,让开发者可以打包他们的应用以及依赖到一个可移植的容器中,然后发布到任何流行的机器上。Docker的迅猛发展和全新理念,席卷了整个IT界,成为云时代的一颗新星。Docker的优势Docker相比于传统虚拟化方式具有更多的优势:docker启动快速...