internal class MessagePump : IServer, IDisposable { // 堆代码 duidaima.com 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
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)对请求报头进行编码。