ASP.NET Core高性能服务器HTTP.SYS
如果我们只需要将ASP.NET CORE应用部署到Windows环境下,并且希望获得更好的性能,那么我们选择的服务器类型应该是HTTP.SYS。Windows环境下任何针对HTTP的网络监听器/服务器在性能上都无法与HTTP.SYS比肩。
一、HTTP.SYS简介
二、MessagePump & UseHttpSys
三、HttpSysOptions
一、HTTP.SYS简介
HTTP.SYS本质上就是一个HTTP/HTTPS监听器,它是Windows网络子系统的一部分,是一个在内核模式下运行的网络驱动。HTTP.SYS对应的驱动文件为“%WinDir\System32\drivers\http.sys”,不要小看这个只有1M多的文件,Windows系统针对HTTP的监听、接收、转发和响应大都依赖它。如图1所示,HTTP.SYS建立在Windows网络子系统针对TCPIP协议栈的驱动(TCPIP.SYS)之上,并为用户态运行的IIS提供基础的HTTP通信服务。前面我们使用的HttpListener也建立在HTTP.SYS上面。

图1 HTTP.SYS
由于HTTP.SYS是在操作系统内核态运行,所以它提供的性能优势是其他在用户态运行的同类产品无法比拟的。由于它自身提供响应缓存,所以在缓存命中的情况下根本不需要与用户态进程进行交互。它还提供了请求队列(Request Queue),如果请求的目标进程(比如IIS的工作进程)处于活动状态,它可以直接将请求分它给它,否则请求会暂存于队列中等待目标进程来提取,这样的工作模式既减少了内核态与用户态之间的上下文切换,也确保请求不会丢失。HTTP.SYS还提供连接管理,流量限制,诊断日志等功能,并提供针对Kerberos的Windows认证。
由于HTTP.SYS是一个底层共享的网络驱动,它有效地解决了端口共享的问题。用户态进程会使用地址前缀(含端口号)“接入”HTTP.SYS,后者利用提供的地址前缀来转发请求,多个用户态进程只要保证提供的地址前缀不同就可以了,所以它们可以使用相同的端口号。端口共享使每个用户进程都可以使用标准的80/443端口。
二、MessagePump & UseHttpSys
基于HTTP.SYS的服务器体现为如下这个MessagePump类型,它内部使用一个HttpSysListener对象采用注册的监听地址接入HTTP.SYS。MessagePump提供针对HTTP 1.X、HTTP 2以及HTTPS的支持。对于Windows Server 2022和Windows 11,还支持HTTP 3。IWebHostBuilder接口如下这两个UseHttpSys扩展方法用来完成针对MessagePump的注册。
internal class MessagePump : IServer, IDisposable
{
internal HttpSysListener Listener { get; }
public IFeatureCollection Features { get; }
public MessagePump(IOptions<HttpSysOptions> options, ILoggerFactory loggerFactory,IAuthenticationSchemeProvider authentication);
public Task StartAsync<TContext>(IHttpApplication<TContext> application,CancellationToken cancellationToken);
public Task StopAsync(CancellationToken cancellationToken);
public void Dispose();
} public static class WebHostBuilderHttpSysExtensions
{
[SupportedOSPlatform("windows")]
public static IWebHostBuilder UseHttpSys(this IWebHostBuilder hostBuilder); [SupportedOSPlatform("windows")]
public static IWebHostBuilder UseHttpSys(this IWebHostBuilder hostBuilder,Action<HttpSysOptions> options);
}
如下所示的是在Minimal API下调用UseHttpSys注册MessagePump 服务器的例子。
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseHttpSys();
var app = builder.Build();
app.MapGet("/", () => "Hello World");
app.Run();
三、HttpSysOptions
在调用UseHttpSys扩展方法注册基于HTTP.SYS的MessagePump服务器的时候,我们可以利用提供的Action<HttpSysOptions>委托对相关的配置选项进行设置。HttpSysOptions的UrlPrefixes属性返回注册的监听地址前缀,但是最终是否这种直接注册到服务器上的监听器地址,取决于IServerAddressesFeature特性的PreferHostingUrls属性,这一点与KestrelServer是一致的。
public class HttpSysOptions
{
public UrlPrefixCollection UrlPrefixes { get; }
public RequestQueueMode RequestQueueMode { get; set; }
public string? RequestQueueName { get; set; }
public long RequestQueueLimit { get; set; }
public AuthenticationManager Authentication { get; }
public ClientCertificateMethod ClientCertificateMethod { get; set; }
public long? MaxConnections { get; set; }
public long? MaxRequestBodySize { get; set; }
public int MaxAccepts { get; set; }
public Http503VerbosityLevel Http503Verbosity { get; set; }
public TimeoutManager Timeouts { get; }
public bool AllowSynchronousIO { get; set; }
public bool EnableResponseCaching { get; set; }
public bool ThrowWriteExceptions { get; set; }
public bool UnsafePreferInlineScheduling { get; set; }
public bool UseLatin1RequestHeaders { get; set; }
}
HTTP.SYS利用请求队列来存放待处理的请求,我们可以利用RequestQueueMode属性决定创建一个新的队列或者使用现有的队列。该属性类型为如下这个RequestQueueMode枚举,枚举项Create表示创建新的队列,Attach表示使用现有的以RequestQueueName属性命名的对象,如果该队列不存在会抛出异常。CreateOrAttach提供了一个折中方案,如果指定名称的队列不存在就创建一个以此命名的新队列。该属性的默认值为Create,RequestQueueName属性默认值为Null(代表匿名队列),RequestQueueLimit属性表示队列的容量,默认值为1000。HttpSysOptions承载的很多配置选项只会应用到新创建的请求队列上。
public enum RequestQueueMode
{
Create,
Attach,
CreateOrAttach
}
HttpSysOptions的Authentication属性返回一个AuthenticationManager对象,我们利用它完成针对认证的设置。我们可以利用Schemes属性设置认证方案,该属性默认为None。如果不允许匿名访问,可以将AllowAnonymous属性设为False。如果将AutomaticAuthentication属性返回True(默认值),认证用户将自动赋值给HttpContext上下文的User属性。AuthenticationDisplayName属性用来为认证方案提供一个显示名称。
public sealed class AuthenticationManager
{
public AuthenticationSchemes Schemes { get; set; }
public bool AllowAnonymous {get; set; }
public bool AutomaticAuthentication { get; set; }
public string? AuthenticationDisplayName { get; set; }
} [Flags]
public enum AuthenticationSchemes
{
None = 0x0,
Digest = 0x1,
Negotiate = 0x2,
Ntlm = 0x4,
Basic = 0x8,
Anonymous = 0x8000,
IntegratedWindowsAuthentication = 0x6
}
HTTPS站点可以要求提供证书来对其实施认证,HttpSysOptions的ClientCertificateMethod属性用于设置请求客户端证书的方式,该属性返回如下这个ClientCertificateMethod枚举。在.NET 5之前,客户端证书采用Renegotation的方式来提取的,Renegotiation是在已经建立的SSL/TLS连接上再次发起的一轮“协商握手”,这种方式对应AllowRenegotation枚举项。由于可能带来一些性能和死锁的问题,这种方式在.NET 5之后已经默认禁止了,目前默认的方式是创建SSL/TLS连接的初始阶段就提取该证书,这种方式对应AllowRenegotation枚举项,这也是ClientCertificateMethod属性的默认值。
public enum ClientCertificateMethod
{
NoCertificate,
AllowCertificate,
AllowRenegotation
}
HttpSysOptions的MaxConnections和MaxRequestBodySize属性分别表示最大连接数和请求主体内容的最大字节数,如果它们被设置为Null,意味着忽略对应的限制。这两个属性的默认值分别Null和30,000,000。MaxAccepts属性表示接受的最大并发请求,默认值为当前处理器数量的5倍。如果并发请求数量超过限流设置,后续请求会拒绝处理,此时服务器会直接回复一个状态码为503的响应,与此同时还会根据Http503Verbosity属性设置的等级作相应的处理。如果该属性值为Basic(默认值),当前TCP连接会重置,Full和Limitmed选项会影响响应的状态描述,前者返回详细的Reason Phrase,后者采用标准的“Service Unavailable”。
public enum Http503VerbosityLevel
{
Basic,
Limited,
Full
}
HttpSysOptions的Timeouts属性返回如下这个TimeoutManager对象,我们利用它完成各种超时设置,包括请求主体内容抵达时间(EntityBody)、读取请求主体内容时间(DrainEntityBody),请求在队列中存放的时间(RequestQueue)、连接闲置时间(IdleConnection)和解析请求报头时间(HeaderWait),这些超时时间默认都是两分钟。MinSendBytesPerSecond属性表示响应数据的最小发送率,默认为每秒150字节。
public sealed class TimeoutManager
{
public TimeSpan EntityBody { get; set; }
public TimeSpan DrainEntityBody { get; set; }
public TimeSpan RequestQueue { get; set; }
public TimeSpan IdleConnection { get; set; }
public TimeSpan HeaderWait { get; set; }
public long MinSendBytesPerSecond { get; set; }
}
HttpSysOptions还定义了其他一系列属性。AllowSynchronousIO属性(默认为False)表示是否运行以同步IO的方式完成针对请求和响应主体内容的读写。EnableResponseCaching属性(默认为True)表示允许响应缓存。ThrowWriteExceptions属性(默认为False)表示因断开连接导致写入响应主体内容失败是否需要抛出异常。如果将UnsafePreferInlineScheduling(默认为False)设置为True,意味着会直接在读取请求的IO线程中执行后续的应用代码,否则我们编写的应用代码会分发到线程池中进行处理。这样可以通过避免线程切换减少单个请求的处理耗时,但是会对整体的吞吐量带来负面影响。UseLatin1RequestHeaders属性(默认为False)表示是否采用Latin1字符集(ISO-8859-1)对请求报头进行编码。
ASP.NET Core高性能服务器HTTP.SYS的更多相关文章
- ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解
ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解 1.1. 名词解释 1.2. Kestrel基本工作原理 1.2.1. Kestrel的基本架构 1.2.2. Ke ...
- [转帖]ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解
ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解 https://www.cnblogs.com/vipyoumay/p/7525478.html ASP.NET C ...
- ASP.NET Core WebListener 服务器
原文地址:WebListener server for ASP.NET Core By Tom Dykstra, Chris Ross WebListener是一个只能运行在Windows上的ASP. ...
- 《ASP.NET Core 高性能系列》致敬伟大的.NET斗士甲骨文!
写在开始 三年前,曾写过一篇文章:从.NET和Java之争谈IT这个行业,当时遭到某些自认为懂得java就了不起的Javaer抨击, 现在可以致敬伟大的.NET斗士甲骨文了 (JDK8以上都需要收费, ...
- ASP.NET Core Web服务器
一.Http.sys HTTP.sys是仅能在Windows上运行的适用于ASP.NET Core的Web服务器. HTTP.sys运行在内核态中,极大减少了系统调用次数,运行效率很高:自带生存环境的 ...
- 《ASP.NET Core 高性能系列》关于.NET Core的部署方式
概述,.NET Core应用程序可以创建三种类型的部署:FDD SCD FDE 框架依赖的部署(FDD).顾名思义,框架依赖的部署(FDD)依赖于目标系统上是否存在.NET Core版本.由于.NET ...
- 《ASP.NET Core 高性能系列》ASP.NET Core的启动过程(1)
一.一切从头开始 简述:知道事情的真相就应该从头 开始,下面我们代码先行 public class Program { public static void Main(string[] args) { ...
- 《ASP.NET Core 高性能系列》关于.NET Core的配置信息的若干事项
1.配置文件的相关闲话 Core自身对于配置文件不是必须品,但由上文分析可知ASP.NET Core默认采用appsettings.json作为配置文件,关于配置信息的优先等级 命令行>环境变量 ...
- 《ASP.NET Core 高性能系列》静态文件中间件
一.概述 静态文件(如 HTML.CSS.图片和 JavaScript等文件)是 Web程序直接提供给客户端的直接加载的文件. 较比于程序动态交互的代码而言,其实原理都一样(走Http协议), ASP ...
随机推荐
- vue 控制台错误
控制台显示报错: Uncaught TypeError: WEBPACK_IMPORTED_MODULE_1_vuex.a.store is not a constructor 解决办法: 将new ...
- 微信小程序结合原生JS实现电商模板(二)
接 <微信小程序结合原生JS实现电商模板(一)>,在首页列表加入购物车到购物和模块增删数量,动态计算商品价格实现后,本次提交主要实现了商品详情(还不完善)简单页面,从商品详情页跳转到购物车 ...
- 04 变量 变量作用域 常量final 变量的命名规范
变量 变量是什么:就是可以变化的量! Java是一种强类型语言,每个变量都必须声明其类型. Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域. 注意事项: 每个变量都有类型,类 ...
- 详解Nacos 配置中心客户端配置缓存动态更新的源码实现
Nacos 作为配置中心,当应用程序去访问Nacos动态获取配置源之后,会缓存到本地内存以及磁盘中. 由于Nacos作为动态配置中心,意味着后续配置变更之后需要让所有相关的客户端感知,并更新本地内存! ...
- 2.3 C++STL vector容器详解
文章目录 2.3.1 引入 2.3.2 代码实例 2.3.3 运行结果 总结 2.3.1 引入 vector 容器 动态数组 可变数组 vector容器 单口容器(尾部操作效率高) vector动态增 ...
- vue项目部署到阿里云服务器(windows),Nginx代理!
项目构成: 前端:vue+vant-ui, 数据库:mysql, 后端:node.js 部署方式:nginx代理: 一,首先要拥有自己的服务器,阿里,腾讯都可以,我用的是阿里的: 如果只是做个人项目的 ...
- 昇腾CANN论文上榜CVPR,全景图像生成算法交互性再增强!
摘要:近日,CVPR 2022放榜,基于CANN的AI论文<Interactive Image Synthesis with Panoptic Layout Generation>强势上榜 ...
- 算法 | Java 常见排序算法(纯代码)
目录 汇总 1. 冒泡排序 2. 选择排序 3. 插入排序 4. 快速排序 5. 归并排序 6. 希尔排序 6.1 希尔-冒泡排序(慢) 6.2 希尔-插入排序(快) 7. 堆排序 8. 计数排序 9 ...
- DHCP协议简析
推荐这篇文章,原理及抓包都分析的很好: **推荐这篇文章,原理及抓包都分析的很好:** https://blog.csdn.net/andy_93/article/details/78238931 简 ...
- 基于WebSocket的简易聊天室
用的是Flash + WebSocket 哦~ Flask 之 WebSocket 一.项目结构: 二.导入模块 pip3 install gevent-websocket 三.先来看一个一对一聊天的 ...