一、基本使用

Kestrel 是 ASP.NET Core 应用自带的 Web 服务器,WebApplication.CreateBuilder 启动的应用默认就在用 Kestrel,不需要额外安装任何包。

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello from Kestrel");

app.Run(); // 此时 Kestrel 已在监听

不配置时,默认监听:

  • http://localhost:5000

  • https://localhost:5001(存在开发证书时)

直接 dotnet run 即可对外服务,这就是它“开箱即用”的一面。

二、配置监听地址的几种方式

1. 代码配置(UseKestrel / ConfigureKestrel)

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(5000);                      // 监听所有网卡的 5000
    options.ListenLocalhost(5001);                  // 仅 localhost
    options.ListenAnyIP(5002, listenOptions =>
    {
        listenOptions.UseHttps();                   // 指定端点启用 HTTPS
    });
    options.ListenUnixSocket("/tmp/myapp.sock");    // Unix 域套接字(容器场景性能更好)
});

var app = builder.Build();
app.Run();

2. appsettings.json 配置(推荐,改配置不用改代码)

{
  "Kestrel": {
    "Endpoints": {
      "Http": { "Url": "http://0.0.0.0:5000" },
      "Https": {
        "Url": "https://0.0.0.0:5001",
        "Certificate": {
          "Path": "certs/server.pfx",
          "Password": "证书密码"
        }
      }
    }
  }
}

3. 命令行 / 环境变量

dotnet run --urls "http://0.0.0.0:5000"

或环境变量 ASPNETCORE_URLS=http://0.0.0.0:5000。

优先级:代码中 Listen* 显式配置 > appsettings.json 的 Kestrel 节点 > --urls/环境变量 > 默认值。注意一旦代码里调用了任何 Listen*,ASPNETCORE_URLS 就会被忽略。

三、常用服务器限制配置

直接暴露公网时建议收紧这些参数:

builder.WebHost.ConfigureKestrel(options =>
{
    options.Limits.MaxConcurrentConnections = 1000;        // 最大并发连接
    options.Limits.MaxConcurrentUpgradedConnections = 100; // WebSocket 等升级连接
    options.Limits.MaxRequestBodySize = 10 * 1024 * 1024;  // 请求体上限,默认 30MB
    options.Limits.MaxRequestBufferSize = 1024 * 1024;     // 请求缓冲区
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);   // Keep-Alive 超时
    options.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(30); // 请求头超时

    options.Limits.MinRequestBodyDataRate =
        new MinRateDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
});

单个 Action 也可以覆盖请求体限制:

[RequestSizeLimit(100_000_000)]
[HttpPost("upload")]
public IActionResult Upload() => Ok();

四、HTTP 协议版本

Kestrel 支持 HTTP/1.1、HTTP/2、HTTP/3(.NET 6+):

options.ListenAnyIP(5001, listenOptions =>
{
    listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
    listenOptions.UseHttps(); // HTTP/2 和 HTTP/3 都要求 TLS
});

也可以在 appsettings.json 中按端点配置:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

五、开发环境下的 HTTPS 证书

首次运行时 .NET 会自动生成一个开发证书(dotnet dev-certs https),仅本机信任。生产环境则要:

  • 用正式的 pfx 文件(如上面的 Certificate 配置)

  • 或在容器/K8s 中把证书挂载进来,通过 UseHttps(cert) 加载

  • 或干脆交给前面的 Nginx/网关做 TLS 终结,Kestrel 只跑 HTTP

六、典型部署形态对比

场景架构Kestrel 角色
容器 / K8sKestrel 直接监听 80/443唯一服务器,最简链路
Linux + NginxNginx → Kestrel(localhost:5000)应用服务器
Windows + IISIIS(ANCM) → Kestrel由 IIS 托管进程

容器场景的标准 Dockerfile 写法:

FROM mcr.microsoft.com/dotnet/aspnet:8.0
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
# .NET 8 默认容器镜像已改为监听 8080(非 root 用户)

常见坑

  • 容器里访问不通:默认 localhost:5000 只绑回环地址,容器内必须用 http://+:8080 或 ListenAnyIP 绑 0.0.0.0。

  • 反向代理后拿不到真实 IP:这不是 Kestrel 的问题,需要配置 ForwardedHeaders 中间件并设置 KnownProxies。

  • 改了 appsettings 不生效:检查代码里是否有 Listen* 覆盖了配置文件的端点。