ASP.NET Core 中的 Kestrel Web 服务器
注意
此版本不是本文的最新版本。 有关当前版本,请参阅本文的 .NET 9 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本。
作者:Tom Dykstra、Chris Ross 和 Stephen Halter
Kestrel 是一个跨平台的适用于 Kestrel。 Kestrel 是建议用于 ASP.NET Core 的服务器,默认情况下在 ASP.NET Core 项目模板中对其进行配置。
Kestrel 的功能包括:
- 跨平台:Kestrel 是可在 Windows、Linux 和 macOS 上运行的跨平台 Web 服务器。
- 高性能:Kestrel 经过优化,可有效处理大量并发连接。
- 轻量级:它经过优化,可在资源受限的环境(如容器和边缘设备)中运行。
- 强化了安全性:Kestrel支持 HTTPS 并经过强化可抵御 Web 服务器漏洞。
- 宽协议支持:Kestrel 支持常见的 Web 协议,包括:
- HTTP/1.1、HTTP/2 和 HTTP/3
- WebSockets
- 与 ASP.NET Core 集成:与其他 ASP.NET Core 组件(例如中间件管道、依赖项注入和配置系统)无缝集成。
- 灵活工作负载:Kestrel 支持许多工作负载:
- ASP.NET 应用框架,例如最小 API、MVC、Razor 页、SignalR、Blazor 和 gRPC。
- 使用 YARP 生成反向代理。
- 扩展性:通过配置、中间件和自定义传输自定义 Kestrel。
- 性能诊断:Kestrel 提供内置的性能诊断功能,例如日志记录和指标。
入门
未使用 IIS 托管时,ASP.NET Core 项目模板默认使用 Kestrel。 在下面的模板生成的 Program.cs
中,WebApplication.CreateBuilder 方法在内部调用 UseKestrel:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
有关配置 WebApplication
和 WebApplicationBuilder
的详细信息,请参阅最小 API 快速参考。
可选客户端证书
有关必须使用证书保护应用子集的信息,请参阅可选客户端证书。
附加了调试器的行为
将调试器附加到 Kestrel 进程时,不会强制实施以下超时和速率限制:
- KestrelServerLimits.KeepAliveTimeout
- KestrelServerLimits.RequestHeadersTimeout
- KestrelServerLimits.MinRequestBodyDataRate
- KestrelServerLimits.MinResponseDataRate
- IConnectionTimeoutFeature
- IHttpMinRequestBodyDataRateFeature
- IHttpMinResponseDataRateFeature
其他资源
- 为 ASP.NET Core Kestrel Web 服务器配置终结点
- 对
WebApplication.CreateBuilder
的UseKestrel
方法调用的源 - 为 ASP.NET Core Kestrel Web 服务器配置选项
- 对 ASP.NET Core Kestrel Web 服务器使用 HTTP/2
- 何时对 ASP.NET Core Kestrel Web 服务器使用反向代理
- 对 ASP.NET Core Kestrel Web 服务器使用主机筛选
- ASP.NET Core 项目故障排除和调试
- 在 ASP.NET Core 中强制使用 HTTPS
- 配置 ASP.NET Core 以使用代理服务器和负载均衡器
- RFC 9110:HTTP 语义(第 7.2 节:托管和授权)
- 在 Linux 上使用 UNIX 套接字时,该套接字不会在应用关闭时自动删除。 有关详细信息,请参阅此 GitHub 问题。
注意
从 ASP.NET Core 5.0 开始,Kestrel 的 libuv 传输将过时。 libuv 传输不会接收用于支持新 OS 平台(如 Windows ARM64)的更新,并会在将来的版本中被删除。 删除对过时 UseLibuv 方法的任何调用并改为使用 Kestrel 的默认套接字传输。
Kestrel 是一个跨平台的适用于 Kestrel。 Kestrel 是包含在 ASP.NET Core 项目模板中的 Web 服务器,默认处于启用状态。
Kestrel 支持以下方案:
macOS 的未来版本将支持 †HTTP/2。
.NET Core 支持的所有平台和版本均支持 Kestrel。
入门
未使用 IIS 托管时,ASP.NET Core 项目模板默认使用 Kestrel。 在下面的模板生成的 Program.cs
中,WebApplication.CreateBuilder 方法在内部调用 UseKestrel:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
有关配置 WebApplication
和 WebApplicationBuilder
的详细信息,请参阅最小 API 快速参考。
可选客户端证书
有关必须使用证书保护应用子集的信息,请参阅可选客户端证书。
附加了调试器的行为
将调试器附加到 Kestrel 进程时,不会强制实施以下超时和速率限制:
- KestrelServerLimits.KeepAliveTimeout
- KestrelServerLimits.RequestHeadersTimeout
- KestrelServerLimits.MinRequestBodyDataRate
- KestrelServerLimits.MinResponseDataRate
- IConnectionTimeoutFeature
- IHttpMinRequestBodyDataRateFeature
- IHttpMinResponseDataRateFeature
其他资源
- 为 ASP.NET Core Kestrel Web 服务器配置终结点
- 对
WebApplication.CreateBuilder
的UseKestrel
方法调用的源 - 为 ASP.NET Core Kestrel Web 服务器配置选项
- 对 ASP.NET Core Kestrel Web 服务器使用 HTTP/2
- 何时对 ASP.NET Core Kestrel Web 服务器使用反向代理
- 对 ASP.NET Core Kestrel Web 服务器使用主机筛选
- ASP.NET Core 项目故障排除和调试
- 在 ASP.NET Core 中强制使用 HTTPS
- 配置 ASP.NET Core 以使用代理服务器和负载均衡器
- RFC 9110:HTTP 语义(第 7.2 节:托管和授权)
- 在 Linux 上使用 UNIX 套接字时,该套接字不会在应用关闭时自动删除。 有关详细信息,请参阅此 GitHub 问题。
注意
从 ASP.NET Core 5.0 开始,Kestrel 的 libuv 传输将过时。 libuv 传输不会接收用于支持新 OS 平台(如 Windows ARM64)的更新,并会在将来的版本中被删除。 删除对过时 UseLibuv 方法的任何调用并改为使用 Kestrel 的默认套接字传输。
Kestrel 是一个跨平台的适用于 Kestrel。 Kestrel 是包含在 ASP.NET Core 项目模板中的 Web 服务器,默认处于启用状态。
Kestrel 支持以下方案:
macOS 的未来版本将支持 †HTTP/2。
.NET Core 支持的所有平台和版本均支持 Kestrel。
入门
未使用 IIS 托管时,ASP.NET Core 项目模板默认使用 Kestrel。 在 Program.cs
中,ConfigureWebHostDefaults 方法调用 UseKestrel:
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
有关生成主机的详细信息,请参阅 ASP.NET Core 中的 .NET 通用主机的“设置主机”和“默认生成器设置”部分。
可选客户端证书
有关必须使用证书保护应用子集的信息,请参阅可选客户端证书。
其他资源
- 为 ASP.NET Core Kestrel Web 服务器配置终结点
- 为 ASP.NET Core Kestrel Web 服务器配置选项
- 对 ASP.NET Core Kestrel Web 服务器使用 HTTP/2
- 何时对 ASP.NET Core Kestrel Web 服务器使用反向代理
- 对 ASP.NET Core Kestrel Web 服务器使用主机筛选
- ASP.NET Core 项目故障排除和调试
- 在 ASP.NET Core 中强制使用 HTTPS
- 配置 ASP.NET Core 以使用代理服务器和负载均衡器
- RFC 9110:HTTP 语义(第 7.2 节:托管和授权)
- 在 Linux 上使用 UNIX 套接字时,该套接字不会在应用关闭时自动删除。 有关详细信息,请参阅此 GitHub 问题。
注意
从 ASP.NET Core 5.0 开始,Kestrel 的 libuv 传输将过时。 libuv 传输不会接收用于支持新 OS 平台(如 Windows ARM64)的更新,并会在将来的版本中被删除。 删除对过时 UseLibuv 方法的任何调用并改为使用 Kestrel 的默认套接字传输。
Kestrel 是一个跨平台的适用于 Kestrel。 Kestrel 是 Web 服务器,默认包括在 ASP.NET Core 项目模板中。
Kestrel 支持以下方案:
- HTTPS
- 用于启用 WebSocket 的不透明升级
- 用于获得 Nginx 高性能的 Unix 套接字
- HTTP/2(在 macOS† 上除外)
macOS 的未来版本将支持 †HTTP/2。
.NET Core 支持的所有平台和版本均支持 Kestrel。
HTTP/2 支持
如果满足以下基本要求,将为 ASP.NET Core 应用提供 HTTP/2:
- 操作系统†
- Windows Server 2016/Windows 10 或更高版本‡
- 具有 OpenSSL 1.0.2 或更高版本的 Linux(例如,Ubuntu 16.04 或更高版本)
- 目标框架:.NET Core 2.2 或更高版本
- 应用程序层协议协商 (ALPN) 连接
- TLS 1.2 或更高版本的连接
macOS 的未来版本将支持 †HTTP/2。 ‡Kestrel 在 Windows Server 2012 R2 和 Windows 8.1 上对 HTTP/2 的支持有限。 支持受限是因为可在这些操作系统上使用的受支持 TLS 密码套件列表有限。 可能需要使用椭圆曲线数字签名算法 (ECDSA) 生成的证书来保护 TLS 连接。
如果已建立 HTTP/2 连接,HttpRequest.Protocol 会报告 HTTP/2
。
从 .NET Core 3.0 开始,HTTP/2 默认处于启用状态。 有关配置的详细信息,请参阅 Kestrel 选项和 ListenOptions.Protocols 部分。
何时将 Kestrel 与反向代理结合使用
Kestrel 可以单独使用,也可以与反向代理服务器一起使用。 反向代理服务器接收来自网络的 HTTP 请求,并将这些请求转发到 Kestrel。 反向代理服务器的示例包括:
Kestrel 用作边缘(面向 Internet)Web 服务器:
Kestrel 用于反向代理配置:
无论配置是否使用反向代理服务器,都是受支持的托管配置。
在没有反向代理服务器的情况下用作边缘服务器的 Kestrel 不支持在多个进程间共享相同的 IP 和端口。 如果将 Kestrel 配置为侦听某个端口,Kestrel 会处理该端口的所有流量(无视请求的 Host
标头)。 可以共享端口的反向代理能在唯一的 IP 和端口上将请求转发至 Kestrel。
即使不需要反向代理服务器,使用反向代理服务器可能也是个不错的选择。
反向代理:
- 可以限制所承载的应用中的公开的公共外围应用。
- 提供额外的配置和深度防御网络安全层。
- 可以更好地与现有基础结构集成。
- 简化了负载均和和安全通信 (HTTPS) 配置。 仅反向代理服务器需要 X.509 证书,并且该服务器可使用普通 HTTP 在内部网络上与应用服务器通信。
警告
采用反向代理配置进行托管需要转接头中间件配置。
ASP.NET Core 应用中的 Kestrel
默认情况下,ASP.NET Core 项目模板使用 Kestrel。 在 Program.cs
中,ConfigureWebHostDefaults 方法调用 UseKestrel:
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
有关生成主机的详细信息,请参阅 ASP.NET Core 中的 .NET 通用主机的“设置主机”和“默认生成器设置”部分。
若要在调用 ConfigureWebHostDefaults
后提供其他配置,请使用 ConfigureKestrel
:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(serverOptions =>
{
// Set properties and call methods on options
})
.UseStartup<Startup>();
});
Kestrel 选项
Kestrel Web 服务器具有约束配置选项,这些选项在面向 Internet 的部署中尤其有用。
对 KestrelServerOptions 类的 Limits 属性设置约束。 Limits
属性包含 KestrelServerLimits 类的实例。
下面的示例使用 Microsoft.AspNetCore.Server.Kestrel.Core 命名空间。
using Microsoft.AspNetCore.Server.Kestrel.Core;
在本文后面的示例中,Kestrel 选项是采用 C# 代码配置的。 还可以使用Kestrel设置 Kestrel 选项。 例如,文件配置提供程序可以从 appsettings.json
或 appsettings.{Environment}.json
文件加载 Kestrel 配置:
{
"Kestrel": {
"Limits": {
"MaxConcurrentConnections": 100,
"MaxConcurrentUpgradedConnections": 100
},
"DisableStringReuse": true
}
}
注意
KestrelServerOptions 和 KestrelServerOptions 可以通过配置提供程序进行配置。 其余的 Kestrel 配置必须采用 C# 代码进行配置。
使用以下方法之一:
在
Startup.ConfigureServices
中配置 Kestrel:将
IConfiguration
的实例注入到Startup
类中。 下面的示例假定注入的配置已分配给Configuration
属性。在
Startup.ConfigureServices
中,将配置的Kestrel
部分加载到 Kestrel 的配置中:using Microsoft.Extensions.Configuration public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.Configure<KestrelServerOptions>( Configuration.GetSection("Kestrel")); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... } }
生成主机时,配置 Kestrel:
在
Program.cs
中,将配置的Kestrel
部分加载到 Kestrel 的配置中:// using Microsoft.Extensions.DependencyInjection; public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((context, services) => { services.Configure<KestrelServerOptions>( context.Configuration.GetSection("Kestrel")); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
上述两种方法适用于任何配置提供程序。
保持活动状态超时
获取或设置保持活动状态超时。 默认值为 2 分钟。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
serverOptions.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Listen(IPAddress.Loopback, 5000);
serverOptions.Listen(IPAddress.Loopback, 5001,
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx",
"testPassword");
});
serverOptions.Limits.KeepAliveTimeout =
TimeSpan.FromMinutes(2);
serverOptions.Limits.RequestHeadersTimeout =
TimeSpan.FromMinutes(1);
})
客户端最大连接数
MaxConcurrentConnections MaxConcurrentUpgradedConnections
可使用以下代码为整个应用设置并发打开的最大 TCP 连接数:
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
serverOptions.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Listen(IPAddress.Loopback, 5000);
serverOptions.Listen(IPAddress.Loopback, 5001,
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx",
"testPassword");
});
serverOptions.Limits.KeepAliveTimeout =
TimeSpan.FromMinutes(2);
serverOptions.Limits.RequestHeadersTimeout =
TimeSpan.FromMinutes(1);
})
对于已从 HTTP 或 HTTPS 升级到另一个协议(例如,Websocket 请求)的连接,有一个单独的限制。 连接升级后,不会计入 MaxConcurrentConnections
限制。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
serverOptions.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Listen(IPAddress.Loopback, 5000);
serverOptions.Listen(IPAddress.Loopback, 5001,
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx",
"testPassword");
});
serverOptions.Limits.KeepAliveTimeout =
TimeSpan.FromMinutes(2);
serverOptions.Limits.RequestHeadersTimeout =
TimeSpan.FromMinutes(1);
})
默认情况下,最大连接数不受限制 (NULL)。
请求正文最大大小
默认的请求正文最大大小为 30,000,000 字节,大约 28.6 MB。
在 ASP.NET Core MVC 应用中替代限制的推荐方法是在操作方法上使用 RequestSizeLimitAttribute 属性:
[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()
以下示例演示如何为每个请求上的应用配置约束:
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
serverOptions.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Listen(IPAddress.Loopback, 5000);
serverOptions.Listen(IPAddress.Loopback, 5001,
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx",
"testPassword");
});
serverOptions.Limits.KeepAliveTimeout =
TimeSpan.FromMinutes(2);
serverOptions.Limits.RequestHeadersTimeout =
TimeSpan.FromMinutes(1);
})
在中间件中替代特定请求的设置:
app.Run(async (context) =>
{
context.Features.Get<IHttpMaxRequestBodySizeFeature>()
.MaxRequestBodySize = 10 * 1024;
var minRequestRateFeature =
context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
var minResponseRateFeature =
context.Features.Get<IHttpMinResponseDataRateFeature>();
if (minRequestRateFeature != null)
{
minRequestRateFeature.MinDataRate = new MinDataRate(
bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
}
if (minResponseRateFeature != null)
{
minResponseRateFeature.MinDataRate = new MinDataRate(
bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
}
如果应用在开始读取请求后配置请求限制,则会引发异常。 IsReadOnly
属性指示 MaxRequestBodySize
属性处于只读状态,意味已经无法再配置限制。
当应用在 ASP.NET Core 模块后于进程外运行时,由于 IIS 已设置限制,因此禁用了 Kestrel 的请求正文大小限制。
请求正文最小数据速率
MinRequestBodyDataRate MinResponseDataRate
Kestrel 每秒检查一次数据是否以指定的速率(字节/秒)传入。 如果速率低于最小值,则连接超时。宽限期是 Kestrel 提供给客户端用于将其发送速率提升到最小值的时间量;在此期间不会检查速率。 宽限期有助于避免最初由于 TCP 慢启动而以较慢速率发送数据的连接中断。
默认的最小速率为 240 字节/秒,包含 5 秒的宽限期。
最小速率也适用于响应。 除了属性和接口名称中具有 RequestBody
或 Response
以外,用于设置请求限制和响应限制的代码相同。
以下示例演示如何在 Program.cs
中配置最小数据速率:
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
serverOptions.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Listen(IPAddress.Loopback, 5000);
serverOptions.Listen(IPAddress.Loopback, 5001,
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx",
"testPassword");
});
serverOptions.Limits.KeepAliveTimeout =
TimeSpan.FromMinutes(2);
serverOptions.Limits.RequestHeadersTimeout =
TimeSpan.FromMinutes(1);
})
在中间件中替代每个请求的最低速率限制:
app.Run(async (context) =>
{
context.Features.Get<IHttpMaxRequestBodySizeFeature>()
.MaxRequestBodySize = 10 * 1024;
var minRequestRateFeature =
context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
var minResponseRateFeature =
context.Features.Get<IHttpMinResponseDataRateFeature>();
if (minRequestRateFeature != null)
{
minRequestRateFeature.MinDataRate = new MinDataRate(
bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
}
if (minResponseRateFeature != null)
{
minResponseRateFeature.MinDataRate = new MinDataRate(
bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
}
用于 HTTP/2 请求的 HttpContext.Features
中不存在前面示例中引用的 IHttpMinResponseDataRateFeature,因为鉴于协议支持请求多路复用,HTTP/2 通常不支持按请求修改速率限制。 不过,用于 HTTP/2 请求的 HttpContext.Features
中仍存在 IHttpMinRequestBodyDataRateFeature,因为仍可以通过将 IHttpMinRequestBodyDataRateFeature.MinDataRate
设置为 null
(甚至对于 HTTP/2 请求),按请求完全禁用读取速率限制。 对于给定 HTTP/2 请求,尝试读取 IHttpMinRequestBodyDataRateFeature.MinDataRate
或尝试将它设置为除 null
以外的值会导致 NotSupportedException
抛出。
通过 KestrelServerOptions.Limits
配置的服务器范围的速率限制仍适用于 HTTP/1.x 和 HTTP/2 连接。
请求标头超时
获取或设置服务器接收请求标头所花费的最大时间量。 默认值为 30 秒。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
serverOptions.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
serverOptions.Listen(IPAddress.Loopback, 5000);
serverOptions.Listen(IPAddress.Loopback, 5001,
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx",
"testPassword");
});
serverOptions.Limits.KeepAliveTimeout =
TimeSpan.FromMinutes(2);
serverOptions.Limits.RequestHeadersTimeout =
TimeSpan.FromMinutes(1);
})
每个连接的最大流
Http2.MaxStreamsPerConnection
限制每个 HTTP/2 连接的并发请求流的数量。 拒绝过多的流。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.Http2.MaxStreamsPerConnection = 100;
});
默认值为 100。
标题表大小
HPACK 解码器解压缩 HTTP/2 连接的 HTTP 标头。 Http2.HeaderTableSize
限制 HPACK 解码器使用的标头压缩表的大小。 该值以八位字节提供,且必须大于零 (0)。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.Http2.HeaderTableSize = 4096;
});
默认值为 4096。
最大帧大小
Http2.MaxFrameSize
表示服务器接收或发送的 HTTP/2 连接帧有效负载的最大允许大小。 该值以八位字节提供,必须介于 2^14 (16,384) 和 2^24-1 (16,777,215) 之间。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.Http2.MaxFrameSize = 16384;
});
默认值为 2^14 (16,384)。
最大请求标头大小
Http2.MaxRequestHeaderFieldSize
表示请求标头值的允许的最大大小(用八进制表示)。 此限制适用于名称和值的压缩和未压缩表示形式。 该值必须大于零 (0)。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192;
});
默认值为 8,192。
初始连接窗口大小
Http2.InitialConnectionWindowSize
表示服务器一次性缓存的最大请求主体数据大小(每次连接时在所有请求(流)中汇总,以字节为单位)。 请求也受 Http2.InitialStreamWindowSize
限制。 该值必须大于或等于 65,535,并小于 2^31 (2,147,483,648)。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.Http2.InitialConnectionWindowSize = 131072;
});
默认值为 128 KB (131,072)。
初始流窗口大小
Http2.InitialStreamWindowSize
表示服务器针对每个请求(流)的一次性缓存的最大请求主体数据大小(以字节为单位)。 请求也受 Http2.InitialConnectionWindowSize
限制。 该值必须大于或等于 65,535,并小于 2^31 (2,147,483,648)。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.Http2.InitialStreamWindowSize = 98304;
});
默认值为 96 KB (98,304)。
预告片
HTTP 尾部类似于 HTTP 标头,只不过它是在发送响应正文后发送的。 IIS 和 HTTP.sys 仅支持 HTTP/2 响应尾部。
if (httpContext.Response.SupportsTrailers())
{
httpContext.Response.DeclareTrailer("trailername");
// Write body
httpContext.Response.WriteAsync("Hello world");
httpContext.Response.AppendTrailer("trailername", "TrailerValue");
}
在前面的示例代码中:
SupportsTrailers
确保响应支持尾部。DeclareTrailer
将给定的尾部名称添加到Trailer
响应头。 虽然并不是必须要声明响应尾部,但是建议这样做。 如果要调用DeclareTrailer
,则必须在发送响应标头之前进行此操作。AppendTrailer
追加尾部。
重置
通过“Reset”,服务器可以使用指定的错误代码重置 HTTP/2 请求。 重置请求被视为中止。
var resetFeature = httpContext.Features.Get<IHttpResetFeature>();
resetFeature.Reset(errorCode: 2);
前述代码示例中的 Reset
指定 INTERNAL_ERROR
错误代码。 有关 HTTP/2 错误代码的详细信息,请访问“HTTP/2 规范错误代码”部分。
同步 I/O
AllowSynchronousIO 控制是否允许对请求和响应使用同步 I/O。 默认值为 false
。
警告
大量阻止同步 I/O 的操作可能会导致线程池资源不足,进而导致应用无响应。 仅在使用不支持异步 I/O 的库时,才启用 AllowSynchronousIO
。
以下示例会启用同步 I/O:
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.AllowSynchronousIO = true;
})
有关其他 Kestrel 选项和限制的信息,请参阅:
终结点配置
默认情况下,ASP.NET Core 绑定到:
http://localhost:5000
https://localhost:5001
(存在本地开发证书时)
使用以下内容指定 URL:
ASPNETCORE_URLS
环境变量。--urls
命令行参数。urls
主机配置键。UseUrls
扩展方法。
采用这些方法提供的值可以是一个或多个 HTTP 和 HTTPS 终结点(如果默认证书可用,则为 HTTPS)。 将值配置为以分号分隔的列表(例如 "Urls": "http://localhost:8000;http://localhost:8001"
)。
关于开发证书的创建:
- 安装了 .NET Core SDK 时。
- dev-certs tool 用于创建证书。
某些浏览器需要授予显式权限才能信任本地开发证书。
项目模板将应用配置为默认情况下在 HTTPS 上运行,并包括 HTTPS 重定向和 HSTS 支持。
调用 KestrelServerOptions 上的 Listen 或 ListenUnixSocket 方法以配置 URL 前缀和 Kestrel 的端口。
UseUrls
、--urls
命令行参数、urls
主机配置键以及 ASPNETCORE_URLS
环境变量也有用,但具有本节后面注明的限制(必须要有可用于 HTTPS 终结点配置的默认证书)。
KestrelServerOptions
配置:
ConfigureEndpointDefaults(Action<ListenOptions>)
指定一个为每个指定的终结点运行的配置 Action
。 多次调用 ConfigureEndpointDefaults
,用最新指定的 Action
替换之前的 Action
。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureEndpointDefaults(listenOptions =>
{
// Configure endpoint defaults
});
});
注意
通过在调用 ConfigureEndpointDefaults 之前调用 Listen 创建的终结点将不会应用默认值。
ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>)
指定一个为每个 HTTPS 终结点运行的配置 Action
。 多次调用 ConfigureHttpsDefaults
,用最新指定的 Action
替换之前的 Action
。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(listenOptions =>
{
// certificate is an X509Certificate2
listenOptions.ServerCertificate = certificate;
});
});
注意
通过在调用 ConfigureHttpsDefaults 之前调用 Listen 创建的终结点将不会应用默认值。
Configure(IConfiguration)
创建配置加载程序,用于设置将 IConfiguration 作为输入的 Kestrel。 配置必须针对 Kestrel 的配置节。
ListenOptions.UseHttps
将 Kestrel 配置为使用 HTTPS。
ListenOptions.UseHttps
扩展:
UseHttps
:将 Kestrel 配置为使用 HTTPS,采用默认证书。 如果没有配置默认证书,则会引发异常。UseHttps(string fileName)
UseHttps(string fileName, string password)
UseHttps(string fileName, string password, Action<HttpsConnectionAdapterOptions> configureOptions)
UseHttps(StoreName storeName, string subject)
UseHttps(StoreName storeName, string subject, bool allowInvalid)
UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location)
UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location, Action<HttpsConnectionAdapterOptions> configureOptions)
UseHttps(X509Certificate2 serverCertificate)
UseHttps(X509Certificate2 serverCertificate, Action<HttpsConnectionAdapterOptions> configureOptions)
UseHttps(Action<HttpsConnectionAdapterOptions> configureOptions)
ListenOptions.UseHttps
参数:
filename
是证书文件的路径和文件名,关联包含应用内容文件的目录。password
是访问 X.509 证书数据所需的密码。configureOptions
是配置HttpsConnectionAdapterOptions
的Action
。 返回ListenOptions
。storeName
是从中加载证书的证书存储。subject
是证书的主题名称。allowInvalid
指示是否存在需要留意的无效证书,例如自签名证书。location
是从中加载证书的存储位置。serverCertificate
是 X.509 证书。
在生产中,必须显式配置 HTTPS。 至少必须提供默认证书。
下面要描述的支持的配置:
- 无配置
- 从配置中替换默认证书
- 更改代码中的默认值
无配置
Kestrel 在 http://localhost:5000
和 https://localhost:5001
上进行侦听(如果默认证书可用)。
从配置中替换默认证书
CreateDefaultBuilder
在默认情况下调用 Configure(context.Configuration.GetSection("Kestrel"))
来加载 Kestrel 配置。 Kestrel 可以使用默认 HTTPS 应用设置配置架构。 从磁盘上的文件或从证书存储中配置多个终结点,包括要使用的 URL 和证书。
在以下 appsettings.json
示例中:
- 将 AllowInvalid 设置为 ,从而允许使用无效证书(例如自签名证书)。
- 任何未指定证书的 HTTPS 终结点(下例中的 HttpsDefaultCert)会回退至在 Certificates > Default 下定义的证书或开发证书。
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
},
"HttpsInlineCertFile": {
"Url": "https://localhost:5001",
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
},
"HttpsInlineCertStore": {
"Url": "https://localhost:5002",
"Certificate": {
"Subject": "<subject; required>",
"Store": "<certificate store; required>",
"Location": "<location; defaults to CurrentUser>",
"AllowInvalid": "<true or false; defaults to false>"
}
},
"HttpsDefaultCert": {
"Url": "https://localhost:5003"
},
"Https": {
"Url": "https://*:5004",
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
}
},
"Certificates": {
"Default": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
}
}
}
此外还可以使用任何证书节点的 Path 和 Password,采用证书存储字段指定证书 。 例如,可将 CertificatesDefault 证书指定为:
"Default": {
"Subject": "<subject; required>",
"Store": "<cert store; required>",
"Location": "<location; defaults to CurrentUser>",
"AllowInvalid": "<true or false; defaults to false>"
}
架构的注意事项:
- 终结点的名称不区分大小写。 例如,
HTTPS
和Https
都是有效的。 - 每个终结点都要具备
Url
参数。 此参数的格式和顶层Urls
配置参数一样,只不过它只能有单个值。 - 这些终结点不会添加进顶层
Urls
配置中定义的终结点,而是替换它们。 通过Listen
在代码中定义的终结点与在配置节中定义的终结点相累积。 Certificate
部分是可选的。 如果为指定Certificate
部分,则使用在之前的方案中定义的默认值。 如果没有可用的默认值,服务器会引发异常且无法启动。Certificate
部分支持 Path–Password 和 Subject–Store 证书。- 只要不会导致端口冲突,就能以这种方式定义任何数量的终结点。
options.Configure(context.Configuration.GetSection("{SECTION}"))
通过.Endpoint(string name, listenOptions => { })
方法返回KestrelConfigurationLoader
,可以用于补充已配置的终结点设置:
webBuilder.UseKestrel((context, serverOptions) =>
{
serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
.Endpoint("HTTPS", listenOptions =>
{
listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12;
});
});
可以直接访问 KestrelServerOptions.ConfigurationLoader
以继续迭代现有加载程序,例如由 CreateDefaultBuilder 提供的加载程序。
- 每个终结点的配置节都可用于
Endpoint
方法中的选项,以便读取自定义设置。 - 通过另一节再次调用
options.Configure(context.Configuration.GetSection("{SECTION}"))
可能加载多个配置。 只使用最新配置,除非之前的实例上显式调用了Load
。 元包不会调用Load
,所以可能会替换它的默认配置节。 KestrelConfigurationLoader
从KestrelServerOptions
将 API 的Listen
簇反射为Endpoint
重载,因此可在同样的位置配置代码和配置终结点。 这些重载不使用名称,且只使用配置中的默认设置。
更改代码中的默认值
可以使用 ConfigureEndpointDefaults
和 ConfigureHttpsDefaults
更改 ListenOptions
和 HttpsConnectionAdapterOptions
的默认设置,包括重写之前的方案指定的默认证书。 需要在配置任何终结点之前调用 ConfigureEndpointDefaults
和 ConfigureHttpsDefaults
。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureEndpointDefaults(listenOptions =>
{
// Configure endpoint defaults
});
serverOptions.ConfigureHttpsDefaults(listenOptions =>
{
listenOptions.SslProtocols = SslProtocols.Tls12;
});
});
Kestrel 支持 SNI
服务器名称指示 (SNI) 可用于承载相同 IP 地址和端口上的多个域。 为了运行 SNI,客户端在 TLS 握手过程中将进行安全会话的主机名发送至服务器,从而让服务器可以提供正确的证书。 在 TLS 握手后的安全会话期间,客户端将服务器提供的证书用于与服务器进行加密通信。
Kestrel 通过 ServerCertificateSelector
回调支持 SNI。 每次连接调用一次回调,从而允许应用检查主机名并选择合适的证书。
SNI 支持要求:
- 在目标框架
netcoreapp2.1
或更高版本上运行。 在net461
或最高版本上,将调用回调,但是name
始终为null
。 如果客户端未在 TLS 握手过程中提供主机名参数,则name
也为null
。 - 所有网站在相同的 Kestrel 实例上运行。 Kestrel 在无反向代理时不支持跨多个实例共享一个 IP 地址和端口。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5005, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
var localhostCert = CertificateLoader.LoadFromStoreCert(
"localhost", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var exampleCert = CertificateLoader.LoadFromStoreCert(
"example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var subExampleCert = CertificateLoader.LoadFromStoreCert(
"sub.example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var certs = new Dictionary<string, X509Certificate2>(
StringComparer.OrdinalIgnoreCase);
certs["localhost"] = localhostCert;
certs["example.com"] = exampleCert;
certs["sub.example.com"] = subExampleCert;
httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
{
if (name != null && certs.TryGetValue(name, out var cert))
{
return cert;
}
return exampleCert;
};
});
});
});
连接日志记录
调用 UseConnectionLogging 以发出用于进行连接上的字节级别通信的调试级别日志。 连接日志记录有助于排查低级通信中的问题,例如在 TLS 加密期间和代理后。 如果 UseConnectionLogging
放置在 UseHttps
之前,则会记录加密的流量。 如果 UseConnectionLogging
放置于 UseHttps
之后,则会记录解密的流量。
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
{
listenOptions.UseConnectionLogging();
});
});
绑定到 TCP 套接字
Listen 方法绑定至 TCP 套接字,且 options lambda 允许 X.509 证书配置:
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Listen(IPAddress.Loopback, 5000);
serverOptions.Listen(IPAddress.Loopback, 5001,
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx",
"testPassword");
});
})
.UseStartup<Startup>();
});
示例使用 ListenOptions 为终结点配置 HTTPS。 可使用相同 API 为特定终结点配置其他 Kestrel 设置。
在 Windows 上,可以使用 New-SelfSignedCertificate
PowerShell cmdlet 创建自签名证书。 有关不受支持的示例,请参阅 UpdateIISExpressSSLForChrome.ps1
。
在 macOS、Linux 和 Windows 上,可以使用 OpenSSL 创建证书。
绑定到 Unix 套接字
可通过 ListenUnixSocket 侦听 Unix 套接字以提高 Nginx 的性能,如以下示例所示:
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock",
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx",
"testpassword");
});
})
- 在 Nginx 配置文件中,将
server
>location
>proxy_pass
条目设置为http://unix:/tmp/{KESTREL SOCKET}:/;
。{KESTREL SOCKET}
是提供给 ListenUnixSocket 的套接字的名称(例如,上述示例中的kestrel-test.sock
)。 - 确保套接字可由 Nginx (例如
chmod go+w /tmp/kestrel-test.sock
)进行写入。
端口 0
如果指定端口号 0
,Kestrel 将动态绑定到可用端口。 以下示例演示如何确定 Kestrel 在运行时实际绑定到的端口:
public void Configure(IApplicationBuilder app)
{
var serverAddressesFeature =
app.ServerFeatures.Get<IServerAddressesFeature>();
app.UseStaticFiles();
app.Run(async (context) =>
{
context.Response.ContentType = "text/html";
await context.Response
.WriteAsync("<!DOCTYPE html><html lang=\"en\"><head>" +
"<title></title></head><body><p>Hosted by Kestrel</p>");
if (serverAddressesFeature != null)
{
await context.Response
.WriteAsync("<p>Listening on the following addresses: " +
string.Join(", ", serverAddressesFeature.Addresses) +
"</p>");
}
await context.Response.WriteAsync("<p>Request URL: " +
$"{context.Request.GetDisplayUrl()}<p>");
});
}
在应用运行时,控制台窗口输出指示可用于访问应用的动态端口:
Listening on the following addresses: http://127.0.0.1:48508
限制
使用以下方法配置终结点:
- UseUrls
--urls
命令行参数urls
主机配置键ASPNETCORE_URLS
环境变量
若要将代码用于 Kestrel 以外的服务器,这些方法非常有用。 不过,请注意以下限制:
- HTTPS 无法与这些方法结合使用,除非在 HTTPS 终结点配置中提供了默认证书(例如,使用
KestrelServerOptions
配置或配置文件,如本主题前面的部分所示)。 - 如果同时使用
Listen
和UseUrls
方法,Listen
终结点将覆盖UseUrls
终结点。
IIS 终结点配置
使用 IIS 时,由 Listen
或 UseUrls
设置用于 IIS 覆盖绑定的 URL 绑定。 有关详细信息,请参阅 ASP.NET Core 模块主题。
ListenOptions.Protocols
Protocols
属性建立在连接终结点上或为服务器启用的 HTTP 协议(HttpProtocols
)。 从 HttpProtocols
枚举向 Protocols
属性赋值。
HttpProtocols 枚举值 |
允许的连接协议 |
---|---|
Http1 |
仅 HTTP/1.1。 可以在具有 TLS 或没有 TLS 的情况下使用。 |
Http2 |
仅 HTTP/2。 仅当客户端支持先验知识模式时,才可以在没有 TLS 的情况下使用。 |
Http1AndHttp2 |
HTTP/1.1 和 HTTP/2。 HTTP/2 要求客户端在 TLS 应用层协议协商 (ALPN) 握手过程中选择 HTTP/2;否则,连接默认为 HTTP/1.1。 |
任何终结点的默认 ListenOptions.Protocols
值都为 HttpProtocols.Http1AndHttp2
。
HTTP/2 的 TLS 限制:
- TLS 版本 1.2 或更高版本
- 重新协商已禁用
- 压缩已禁用
- 最小的临时密钥交换大小:
- 椭圆曲线 Diffie-Hellman (ECDHE) [RFC4492]:最小 224 位
- 有限字段 Diffie-Hellman (DHE) [
TLS12
]:最小 2048 位
- 不禁止密码套件。
默认情况下,支持具有 P-256 椭圆曲线 [FIPS186
] 的 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[TLS-ECDHE
]。
以下示例允许端口 8000 上的 HTTP/1.1 和 HTTP/2 连接。 TLS 使用提供的证书来保护连接:
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
使用连接中间件,针对特定密码的每个连接筛选 TLS 握手(如有必要)。
下面的示例针对应用不支持的任何密码算法引发 NotSupportedException。 或者,定义 ITlsHandshakeFeature.CipherAlgorithm 并将其与可接受的密码套件列表进行比较。
没有哪种加密是使用 CipherAlgorithmType.Null 密码算法。
// using System.Net;
// using Microsoft.AspNetCore.Connections;
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
listenOptions.UseTlsFilter();
});
});
using System;
using System.Security.Authentication;
using Microsoft.AspNetCore.Connections.Features;
namespace Microsoft.AspNetCore.Connections
{
public static class TlsFilterConnectionMiddlewareExtensions
{
public static IConnectionBuilder UseTlsFilter(
this IConnectionBuilder builder)
{
return builder.Use((connection, next) =>
{
var tlsFeature = connection.Features.Get<ITlsHandshakeFeature>();
if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
{
throw new NotSupportedException("Prohibited cipher: " +
tlsFeature.CipherAlgorithm);
}
return next();
});
}
}
}
连接筛选也可以通过 IConnectionBuilder lambda 进行配置:
// using System;
// using System.Net;
// using System.Security.Authentication;
// using Microsoft.AspNetCore.Connections;
// using Microsoft.AspNetCore.Connections.Features;
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
listenOptions.Use((context, next) =>
{
var tlsFeature = context.Features.Get<ITlsHandshakeFeature>();
if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
{
throw new NotSupportedException(
$"Prohibited cipher: {tlsFeature.CipherAlgorithm}");
}
return next();
});
});
});
在 Linux 上,CipherSuitesPolicy 可用于针对每个连接筛选 TLS 握手:
// using System.Net.Security;
// using Microsoft.AspNetCore.Hosting;
// using Microsoft.AspNetCore.Server.Kestrel.Core;
// using Microsoft.Extensions.DependencyInjection;
// using Microsoft.Extensions.Hosting;
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(listenOptions =>
{
listenOptions.OnAuthenticate = (context, sslOptions) =>
{
sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(
new[]
{
TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
// ...
});
};
});
});
从配置中设置协议
CreateDefaultBuilder
在默认情况下调用 serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
来加载 Kestrel 配置。
以下 appsettings.json
示例将 HTTP/1.1 建立为所有终结点的默认连接协议:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1"
}
}
}
以下 appsettings.json
示例将为所有指定终结点建立 HTTP/1.1 连接协议:
{
"Kestrel": {
"Endpoints": {
"HttpsDefaultCert": {
"Url": "https://localhost:5001",
"Protocols": "Http1"
}
}
}
}
代码中指定的协议覆盖了由配置设置的值。
URL 前缀
如果使用 UseUrls
、--urls
命令行参数、urls
主机配置键或 ASPNETCORE_URLS
环境变量,URL 前缀可采用以下任意格式。
仅 HTTP URL 前缀是有效的。 使用 UseUrls
配置 URL 绑定时,Kestrel 不支持 HTTPS。
包含端口号的 IPv4 地址
http://65.55.39.10:80/
0.0.0.0
是一种绑定到所有 IPv4 地址的特殊情况。包含端口号的 IPv6 地址
http://[0:0:0:0:0:ffff:4137:270a]:80/
[::]
是 IPv40.0.0.0
的 IPv6 等效项。包含端口号的主机名
http://contoso.com:80/ http://*:80/
主机名、
*
和+
并不特殊。 没有识别为有效 IP 地址或localhost
的任何内容都将绑定到所有 IPv4 和 IPv6 IP。 若要将不同主机名绑定到相同端口上的不同 ASP.NET Core 应用,请使用 HTTP.sys 或 IIS、Nginx 或 Apache 等反向代理服务器。警告
采用反向代理配置进行托管需要转接头中间件配置。
包含端口号的主机
localhost
名称或包含端口号的环回 IPhttp://localhost:5000/ http://127.0.0.1:5000/ http://[::1]:5000/
指定
localhost
后,Kestrel 将尝试绑定到 IPv4 和 IPv6 环回接口。 如果其他服务正在任一环回接口上使用请求的端口,则 Kestrel 将无法启动。 如果任一环回接口出于任何其他原因(通常是因为 IPv6 不受支持)而不可用,则 Kestrel 将记录一个警告。
主机筛选
尽管 Kestrel 支持基于前缀的配置(例如 http://example.com:5000
),但 Kestrel 在很大程度上会忽略主机名。 主机 localhost
是一个特殊情况,用于绑定至环回地址。 除了显式 IP 地址以外的所有主机都绑定至所有公共 IP 地址。 不验证 Host
标头。
解决方法是,使用主机筛选中间件。 主机筛选中间件由 Microsoft.AspNetCore.HostFiltering 包提供,此包为 ASP.NET Core 应用隐式提供。 由调用 AddHostFiltering 的 CreateDefaultBuilder 添加中间件:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
默认情况下,主机筛选中间件处于禁用状态。 要启用该中间件,请在 appsettings.json
/appsettings.{Environment}.json
中定义一个 AllowedHosts
键。 此值是以分号分隔的不带端口号的主机名列表:
appsettings.json
:
{
"AllowedHosts": "example.com;localhost"
}
注意
转接头中间件 同样包含 AllowedHosts 选项。 转接头中间件和主机筛选中间件具有适合不同方案的相似功能。 如果未保留 Host
标头,并且使用反向代理服务器或负载均衡器转接请求,则使用转接头中间件设置 AllowedHosts
比较合适。 将 Kestrel 用作面向公众的边缘服务器或直接转接 Host
标头时,使用主机筛选中间件设置 AllowedHosts
比较合适。
有关转接头中间件的详细信息,请参阅配置 ASP.NET Core 以使用代理服务器和负载均衡器。
Libuv 传输配置
对于需要使用 Libuv (UseLibuv) 的项目:
将
Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
包的依赖项添加到应用的项目文件中:<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" Version="{VERSION}" />
调用
IWebHostBuilder
上的 UseLibuv: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.UseLibuv(); webBuilder.UseStartup<Startup>(); }); }
HTTP/1.1 请求排出
打开 HTTP 连接非常耗时。 对于 HTTPS 而言,这也是资源密集型。 因此,Kestrel 会尝试按 HTTP/1.1 协议重新使用连接。 请求正文必须完全使用才能允许重新使用连接。 应用不会始终使用请求正文,例如 POST
请求,其中服务器返回重定向或 404 响应。 在 POST
重定向的情况下:
- 客户端可能已发送部分
POST
数据。 - 服务器写入 301 响应。
- 在完全读取上一个请求正文中的
POST
数据之前,不能将连接用于新请求。 - Kestrel 尝试排出请求正文。 排出请求正文意味着读取和丢弃数据,而不处理数据。
排出过程会在允许重新使用连接与排出任何剩余数据所用的时间之间进行权衡:
- 排出超时为五秒,该值不可配置。
- 如果
Content-Length
或Transfer-Encoding
标头指定的所有数据在超时之前都未被读取,则连接将关闭。
有时,你可能想要在写入响应之前或之后立即终止请求。 例如,客户端可能具有限制性的数据上限,因此可以优先考虑限制上传的数据。 在这种情况下,若要终止请求,请从控制器、Razor 页面或中间件调用 HttpContext。
在调用 Abort
时,存在一些注意事项:
- 创建新连接可能会很慢且成本高昂。
- 在连接关闭之前无法保证客户端已读取响应。
- 应极少调用
Abort
,并且应将此操作留给严重错误情况(而不是常见错误情况)。- 只有在需要解决特定问题时才调用
Abort
。 例如,如果恶意客户端正在尝试POST
数据或在客户端代码中存在导致大量请求的 bug,则调用Abort
。 - 不要为常见错误情况(如 HTTP 404(找不到))调用
Abort
。
- 只有在需要解决特定问题时才调用
调用 Abort
之前调用 HttpResponse.CompleteAsync 可确保服务器已完成写入响应。 但是,客户端行为是不可预测的,在连接中止前它们可能未读取响应。
对于 HTTP/2,此过程又有所不同,因为协议支持在不关闭连接的情况下中止单个请求流。 五秒排出超时不适用。 如果在完成响应后存在任何未读的请求正文数据,则服务器会发送 HTTP/2 RST 帧。 其他请求正文数据帧将被忽略。
如果可能,客户端最好使用 Expect:100-continue 请求标头,然后等到服务器响应后再开始发送请求正文。 这样,客户端便有机会在发送不需要的数据之前检查响应和中止。
其他资源
- 在 Linux 上使用 UNIX 套接字时,该套接字不会在应用关闭时自动删除。 有关详细信息,请参阅此 GitHub 问题。
- ASP.NET Core 项目故障排除和调试
- 在 ASP.NET Core 中强制使用 HTTPS
- 配置 ASP.NET Core 以使用代理服务器和负载均衡器
- RFC 9110:HTTP 语义(第 7.2 节:托管和授权)