什麼是Kestrel
Kestrel是一個跨平臺的適用於Kestrel。
Kestrel是包含在ASP.NET Core項目模板中的Web服務器,默認處於啓用狀態。
Kestrel支持以下方案:
- HTTPS
- HTTP/2(在macOS†上除外)
- 用於啓用WebSocket的不透明升級
- 用於獲得Nginx高性能的Unix套接字
macOS的未來版本將支持HTTP/2。
.NET Core支持的所有平臺和版本均支持Kestrel。
默認啓用
未使用IIS託管時,ASP.NET Core項目模板默認使用Kestrel。在下面的模板生成的Program.cs
中,WebApplication.CreateBuilder
方法在內部調用UseKestrel
:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
//
// 摘要:
// Extension methods for configuring the IWebHostBuilder.
public static class GenericHostBuilderExtensions
{
//
// 摘要:
// Initializes a new instance of the Microsoft.AspNetCore.Hosting.IWebHostBuilder
// class with pre-configured defaults.
//
// 參數:
// builder:
// The Microsoft.Extensions.Hosting.IHostBuilder instance to configure
//
// configure:
// The configure callback
//
// 返回結果:
// The Microsoft.Extensions.Hosting.IHostBuilder for chaining.
//
// 言論:
// The following defaults are applied to the Microsoft.AspNetCore.Hosting.IWebHostBuilder:
// use Kestrel as the web server and configure it using the application's configuration
// providers, adds the HostFiltering middleware, adds the ForwardedHeaders middleware
// if ASPNETCORE_FORWARDEDHEADERS_ENABLED=true, and enable IIS integration.
public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure);
}
WebApplication.CreateBuilder的UseKestrel
internal static void ConfigureWebDefaults(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration((ctx, cb) =>
{
if (ctx.HostingEnvironment.IsDevelopment())
{
StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);
}
});
builder.UseKestrel((builderContext, options) =>
{
options.Configure(builderContext.Configuration.GetSection("Kestrel"), reloadOnChange: true);
})
.ConfigureServices((hostingContext, services) =>
{
// Fallback
services.PostConfigure<HostFilteringOptions>(options =>
{
if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
{
// "AllowedHosts": "localhost;127.0.0.1;[::1]"
var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
// Fall back to "*" to disable.
options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
}
});
// Change notification
services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));
services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
services.AddTransient<IStartupFilter, ForwardedHeadersStartupFilter>();
services.AddTransient<IConfigureOptions<ForwardedHeadersOptions>, ForwardedHeadersOptionsSetup>();
services.AddRouting();
})
.UseIIS()
.UseIISIntegration();
}
一般限制
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
});
webBuilder.UseStartup<Startup>();
});
{
"Kestrel": {
"Limits": {
"MaxConcurrentConnections": 100,
"MaxConcurrentUpgradedConnections": 100
},
"DisableStringReuse": true
}
}
保持活動狀態超時
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 保持活動狀態超時
kestrelServerOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
});
webBuilder.UseStartup<Startup>();
});
客戶端最大連接數
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 設置最大打開的連接數
kestrelServerOptions.Limits.MaxConcurrentConnections = 100;
// 設置最大打開、升級的連接數,升級的連接是已從HTTP切換到另一個協議(如WebSocket)的連接
kestrelServerOptions.Limits.MaxConcurrentUpgradedConnections = 100;
});
webBuilder.UseStartup<Startup>();
});
請求正文最大大小
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 設置允許的請求正文的最大大小(以字節爲單位)
kestrelServerOptions.Limits.MaxRequestBodySize = 100_000_000;
});
webBuilder.UseStartup<Startup>();
});
請求正文最小數據速率
Kestrel每秒檢查一次數據是否以指定的速率(字節/秒)傳入。如果速率低於最小值,則連接超時。寬限期是Kestrel允許客戶端將其發送速率提升到最小值的時間量。在此期間不會檢查速率。寬限期有助於避免最初由於TCP慢啓動而以較慢速率發送數據的連接中斷。最小速率也適用於響應。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 設置請求正文的最小數據速率(以字節/秒爲單位)
kestrelServerOptions.Limits.MinRequestBodyDataRate = new MinDataRate(
bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
// 設置響應最小數據速率(以字節/秒爲單位)
kestrelServerOptions.Limits.MinResponseDataRate = new MinDataRate(
bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
});
webBuilder.UseStartup<Startup>();
});
請求標頭超時
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 設置服務器接收請求頭所需的最大時間量
kestrelServerOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});
webBuilder.UseStartup<Startup>();
});
HTTP/2限制
每個連接的最大流
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 限制每個HTTP/2 連接的併發請求流的數量(拒絕過多的流)
kestrelServerOptions.Limits.Http2.MaxStreamsPerConnection = 100;
});
webBuilder.UseStartup<Startup>();
});
標題表大小
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 限制了服務器上HPACK編碼器與解碼器可以使用的標頭壓縮表的大小(以八進制數表示)
kestrelServerOptions.Limits.Http2.HeaderTableSize = 4096;
});
webBuilder.UseStartup<Startup>();
});
最大幀大小
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 指示允許接收的最大幀有效負載的大小(以八進制數表示)
kestrelServerOptions.Limits.Http2.MaxFrameSize = 16_384;
});
webBuilder.UseStartup<Startup>();
});
最大請求標頭大小
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 指示請求頭字段序列的最大允許大小
kestrelServerOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192;
});
webBuilder.UseStartup<Startup>();
});
初始連接窗口大小
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 服務器一次願意接收和緩衝多少請求正文數據
kestrelServerOptions.Limits.Http2.InitialConnectionWindowSize = 131_072;
});
webBuilder.UseStartup<Startup>();
});
初始流窗口大小
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 服務器願意爲每個流一次接收和緩衝多少請求正文數據
kestrelServerOptions.Limits.Http2.InitialStreamWindowSize = 98_304;
});
webBuilder.UseStartup<Startup>();
});
保持活動ping配置
Kestrel可以配置爲向連接的客戶端發送HTTP/2 Ping。
HTTP/2 Ping有多種用途:
- 使空閒連接保持活動狀態。某些客戶端和代理服務器會關閉空閒的連接。HTTP/2 Ping是對連接執行的活動,可防止空閒連接被關閉。
- 關閉不正常的連接。服務器會關閉在配置的時間內客戶端未響應保持活動ping的連接。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 配置ping間隔的TimeSpan。如果服務器在此時間段內沒有收到任何幀,則服務器會向客戶端發送保持活動ping。將此選項設置爲TimeSpan.MaxValue時,會禁用保持活動ping。
kestrelServerOptions.Limits.Http2.KeepAlivePingDelay = TimeSpan.FromSeconds(30);
// 配置ping超時的TimeSpan。如果服務器在此超時期間沒有收到任何幀(如響應ping),則連接將關閉。將此選項設置爲TimeSpan.MaxValue時,會禁用保持活動狀態超時。
kestrelServerOptions.Limits.Http2.KeepAlivePingTimeout = TimeSpan.FromMinutes(1);
});
webBuilder.UseStartup<Startup>();
});
同步I/O
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(kestrelServerOptions =>
{
// 配置Kestrel
// 控制是否允許對請求和響應使用同步I/O
kestrelServerOptions.AllowSynchronousIO = true;
});
webBuilder.UseStartup<Startup>();
});
大量阻止同步I/O的操作可能會導致線程池資源不足,進而導致應用無響應。僅在使用不支持異步I/O的庫時,才啓用AllowSynchronousIO