網站首頁 編程語言 正文
如果我們只需要將ASP.NET CORE應用部署到Windows環境下,并且希望獲得更好的性能,那么我們選擇的服務器類型應該是HTTP.SYS。Windows環境下任何針對HTTP的網絡監聽器/服務器在性能上都無法與HTTP.SYS比肩。
一、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(IOptionsoptions, ILoggerFactory loggerFactory,IAuthenticationSchemeProvider authentication); public Task StartAsync (IHttpApplication 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 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
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)對請求報頭進行編碼。
原文鏈接:https://www.cnblogs.com/artech/p/inside-asp-net-core-6-33.html
相關推薦
- 2023-02-12 C++?STL之string的模擬實現實例代碼_C 語言
- 2022-03-27 帶你從編碼角度分析C++重載原理_C 語言
- 2022-03-26 android獲取及監聽手機網絡狀態_Android
- 2022-08-22 探究C#訪問null字段會拋異常原因_C#教程
- 2022-05-17 Spring Cloud OpenFeign源碼解析
- 2023-12-16 IDEA中調用方法時,同步顯示方法的注釋信息
- 2023-10-15 element-ui里el-progress:進度條問題的解決Invalid prop: custo
- 2022-12-24 Docker中redis集群部署實戰_docker
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支