深度理解IIS下部署ASP.NET Core2.1 Web应用拓扑图
原文:深度理解IIS下部署ASP.NET Core2.1 Web应用拓扑图
IIS部署ASP.NET Core2.1 应用拓扑图
我们看到相比Asp.Net, 出现了3个新的组件:ASP.NET Core Module、Kestrel、dotnet.exe, 后面我们会理清楚这三个组件的作用和组件之间的交互原理。
引入Kestrel的原因
进程内HTTP服务器,与老牌web服务器解耦,实现跨平台部署
IIS、Nginx、Apache等老牌web服务器有他们自己的启动进程和环境;为了实现跨平台部署,需要与这些web服务器的功能解耦,网络通信是一个比较好的选择。
作为进程内Http服务器,ASP.NET Core 保持独立运作一个Http服务器的能力,由这些老牌web服务器充当反向代理服务器将请求转发给进程内Http服务器,这样保持了开发过程中配置Startup、Program文件的纯粹性 和部署时候的跨平台能力。
客观上Kestrel还是作为Http服务器,功能还比不上老牌的web服务器
Kestrel自诞生之日起还有一些网络安全方面的缺陷,这些缺陷包括一个合适的timeouts,Size limits,和并发数量等
在内网部署和开发环境中我们完全可以使用Kestrel来充当web服务器。
Kestrel的底层实现细节:Kestrel 要做到跨平台HTTP服务器,需要脱离底层系统细节实现跨平台IO,在Asp.NetCore2.1 版本之前使用libuv(一个高性能跨平台IO库),2.1 版本之后采用的托管Sockets,这是一个巨大的变化,有兴趣的可以搜索一下。
引入ASP.NET Core Module
反向代理服务器的作用是将请求转发给内网的Http服务器,IIS上使用ASP.NET Core Module组件将请求转发到Kestrel Http服务器; 注意该组件只在IIS上有效。
从整个拓扑图上看,请求首先到达内核态Http.sys Driver,该驱动将请求路由到IIS上指定网站;
然后Asp.Net Core Module将请求转发给Kestrel服务器。
作为企业级服务ASP.NET Core Module需要完成:
进程管理: 控制webApp启动进程内Kestrel服务器在某端口上启动,并监听转发请求
故障恢复: 控制webapp在1min内崩溃重启的次数
请求转发
启动日志记录: webapp启动失败,可通过配置将日志输出到指定目录
请求头信息转发:代理服务器需要保证传递 源IP地址、源Scheme、原始Host请求头等信息
转发windiws认证token
以上能力,可以参考https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module?view=aspnetcore-2.1
给出的AspNetCore Module配置参数
自然可以猜想ASP.NET Core Module与IISIntegration()关系很是密切:
Web启动的时候,ASP.NET Core Module会通过环境变量指定kestrel监听的端口;
IIS Integration方法则配置服务器在http://localhost:{指定端口}上监听。
同时开始检查请求是否来自AspNet Core Module(非ASPNE TCore Module转发的请求会被拒绝)
另外由于反向代理服务器的存在,webapp可能会丢失原始请求信息; 比如
- 源IP地址
- scheme: 反向代理服务器和Kestrel之间通过Http交互
- 可能被代理服务器修改的原始Host请求头
这些工作由ForwardedHeader middleware完成,该中间件由UseIISIntegration方法默认开启。
- //------------- 节选自Microsoft.AspNetCore.Hosting.WebHostBuilderIISExtensions---------------------
- 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.
- /// </summary>
- /// <param name="hostBuilder"></param>
- /// <returns></returns>
- public static IWebHostBuilder UseIISIntegration(this IWebHostBuilder hostBuilder)
- {
- if (hostBuilder == null)
- {
- throw new ArgumentNullException(nameof(hostBuilder));
- }
- // Check if `UseIISIntegration` was called already
- if (hostBuilder.GetSetting(nameof(UseIISIntegration)) != null)
- {
- return 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 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 accidently overwrite it.
- hostBuilder.UseSetting(WebHostDefaults.ServerUrlsKey, address);
- hostBuilder.PreferHostingUrls(true);
- 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;
- }
- }
可以看到Web程序在配置启动时读取了5个由AspNET Core Module设置的环境变量。
着重理解Kestrel是怎么拒绝来自非AspNetCore Module转发的请求:
AspNetCore Module 设置TOKEN=XXX环境变量
WebApp启动时读取Token=XXX环境变量
AspNetCore Module在转发请求时,会在Request里面加上一个 MS-ASPNETCORE-TOKEN:XXX的请求头
IISMiddleware中间件将会起作用:携带了该请求头的转发请求被认为有效。
- //---------------节选自Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware----------------------
- public async Task Invoke(HttpContext httpContext)
- {
- if (!string.Equals(_pairingToken, httpContext.Request.Headers[MSAspNetCoreToken], StringComparison.Ordinal))
- {
- _logger.LogError($"'{MSAspNetCoreToken}' does not match the expected pairing token '{_pairingToken}', request rejected.");
- httpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
- return;
- }
- ......
- }
20181205 更新,.NetCore2.2+ ASP.NETCore Module支持进程内托管模型,本文章内容针对AspNetCore2.1
FAQ:
1. 什么叫反向代理服务器Reverse Proxy Server?
通常的代理服务器,只用于代理内部网络对Internet的连接需求,客户机必须指定代理服务器将本来要直接发送到web服务器上的http请求发送到代理服务器中,普通的代理服务器不支持外部对内部网络的访问请求;
当一个代理服务器能够代理外部网络的主机,访问内部网络,这种代理服务器的方式称为反向代理服务器 。
在AspNet Core Web应用IIS、Ngnix转发请求时,内部的Kestrel和Applicaiton Code组成完整的内部网络,IIS、Nginx等web服务器在这里的角色就起到了反向代理作用。
2. 依照上图的拓扑图我们理所当然可以认为背靠在IIS后面的Kestrel应该是可以访问的,因为它也是一个web服务器,那么怎样直接访问背靠在AspNetCore Module后面的的Kestrel服务器?
按照上文的理论,背靠在AspNetCore Module后面的Web进程是依靠 Token来拒绝【非AspNetCore Module转发的请求】。
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module?view=aspnetcore-2.2
因此,将该PairToken拷贝到请求头,我们也是可以在Kestrel behind IIS的情况下,直接访问Kestrel(虽然这种情况不常见,但是对于我们理解拓扑图很有帮助)。
步骤如下:
找到dotnet进程: tasklist | findstr "dotnet"
找到该进程占用port : netstat -ano | findstr {pid}
利用输出的port: curl localhost:{port}, 会提示400 badrequest, 这与源码的返回一致
从error log 中拷贝出该MS-ASPNETCORE-TOKEN, 附在request header中便可以访问
--------------如果你觉得文章对你有价值,请点赞或者关注,支持原创势力,蟹蟹--------------~~。。~~--------------~~。。~~----------------
深度理解IIS下部署ASP.NET Core2.1 Web应用拓扑图的更多相关文章
- Web Server 在iis下部署asp网站在iis下
Web Server 在iis下部署asp网站在iis下 一.参考地址: win7 http://jingyan.baidu.com/article/636f38bb1bbcadd6b846108b. ...
- 在IIs上部署asp.net core2.1项目
转自:https://www.cnblogs.com/jasonduan/p/9193702.html 在IIS上部署你的ASP.NET Core 2.1项目 1.在控制面板→程序→启用或关闭Wi ...
- 【续集】在 IIS 中部署 ASP.NET 5 应用程序遭遇的问题
dudu 的一篇博文:在 IIS 中部署 ASP.NET 5 应用程序遭遇的问题 针对 IIS 部署 ASP.NET 5 应用程序的问题,在上面博文中主要采用两种方式尝试: VS2015 的 Publ ...
- Windows + IIS 环境部署Asp.Net Core App
环境:Windows Server 2012, IIS 8, Asp.Net Core 1.1. 不少人第一次在IIS中部署Asp.Net Core App的人都会遇到问题,会发现原来的部署方式无法运 ...
- Windows Server 2008 R2 + IIS 环境部署Asp.Net Core App
Windows + IIS 环境部署Asp.Net Core App 环境:Windows Server 2012, IIS 8, Asp.Net Core 1.1. 不少人第一次在IIS中部署A ...
- 在IIS中部署Asp.Net网站
在IIS中部署Asp.Net网站 1.添加IIS或者删除IIS,在控制面板=>程序和功能=>打开或关闭功能 启动iis,右键计算机=>管理=>服务和应用程序=>Inter ...
- 在IIS下部署Thinkphp项目,验证码不能显示的解决办法
由于公司租用的是虚拟空间,而且用的是IIS服务器,所以部署PHP的时候就出现很多问题:比如昨天就碰到这个问题:在IIS下部署Thinkphp项目,验证码不能显示 这是生成验证码的方法: // 制作专门 ...
- Ubuntu 下部署asp.net运行环境
在Ubuntu下部署asp.net运行环境,网上教程很多,基本都是编译Mono源码,然后安装jexus.但是可能是我最近RP不太好,编译Mono源码一直都是失败,无奈之下只好找另外的方法安装了. 网上 ...
- 在IIS下部署SSL证书实现HTTPS
在IIS下部署SSL证书实现HTTPS HTTPS是以安全为目标的HTTP通道,简单讲是HTTP的安全版.谷歌已经制定了一项长远的计划,它的最终目标是将所有通过HTTP协议呈现的网页标为“不安全” ...
随机推荐
- STL中向量vector笔记
vector的本质是:数组的封装 特点:读取能在常数时间内完成 Vector成员函数 函数 表述 c.assign(beg,end) c.assign(n,elem) 将[beg; end)区间中的数 ...
- 记号(notation)的学习
数学的记号(notation) 记号具体代表什么含义,取决于你的定义: 比如这样的 d⃗ 一个向量,每个分量 d(i) 表示的是从初始结点 v 到当前节点 vi 的最短路径:也即这样的一个向量的每一 ...
- 36.Node.js 工具模块--OS模块系统操作
转自:http://www.runoob.com/nodejs/nodejs-module-system.html Node.js os 模块提供了一些基本的系统操作函数.我们可以通过以下方式引入该模 ...
- 15.Node.js REPL(交互式解释器)
转自:http://www.runoob.com/nodejs/nodejs-tutorial.html Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电 ...
- 错误 make: Nothing to be done for 'default'
Makefile书写格式非常严格,all:<TAB缩进>make -C $(KDIR) M=$(PWD) $(EXTRA_CFLAGS) modulesdefault:<TAB缩进& ...
- react radio onchange事件点击无效
记: 项目需求: 页面中radio默认选中 第一次进去页面 点击radio的时候不管怎样点击 都是选中 连onChange事件都没触发 进入页面 点击刷新 点击rad ...
- 20160218.CCPP体系具体解释(0028天)
程序片段(01):加法.c 内容概要:字符串计算表达式 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <st ...
- 图像处理 Mine
1)中值滤波:排序取中间值.作用:去噪点 1.1)均值滤波; 1.2)高斯模糊:执行高斯模糊,然后改混合模式,改成叠加.柔光或者深色.就能得到平滑而不模糊的效果. 2)腐蚀.膨胀:开运算(腐蚀后膨胀) ...
- CODEVS——T 1993 草地排水 USACO
http://codevs.cn/problem/1993/ 时间限制: 2 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 De ...
- JS错误记录 - 按左右箭头div移动、一串div跟着鼠标移动
本次练习错误总结: 1. div跟着用户操作而移动,首先必须要绝对定位,否则无法移动. 2. if条件语句里面是双等号,不是单等号(赋值). 3. 坐标值没有Right,只能offsetLeft 加减 ...