Kestrel监听-Http服务

4 阅读7分钟

Kestrel 完整笔记

目录

  1. Kestrel 是什么
  2. 为什么叫"监听"
  3. Kestrel 的真实工作
  4. 系统主地址概念
  5. 编辑工具的地址
  6. 不同部署场景的地址配置
  7. 完整配置示例

1. Kestrel 是什么

1.1 官方定义

Kestrel = ASP.NET Core 内置的跨平台 Web 服务器

1.2 通俗理解

Kestrel = 监听服务 + 构建服务

Kestrel 的双重职责:
​
1. 监听服务(Listening Service)
   - 在网络端口上监听
   - 等待和接收 HTTP 请求
   - 这是"守门员"的角色
​
2. 构建服务(Building Service)
   - 构建整个系统的 HTTP 服务能力
   - 提供 HTTP 协议处理
   - 搭建请求-响应的基础设施
   - 这是"建筑工人"的角色

Kestrel = 你的程序的 HTTP 服务引擎

它是一个软件组件,负责:

1.3 形象比喻

你的 ASP.NET Core 程序 = 一家餐厅
​
Kestrel = 餐厅的前台接待员
    ├─ 在门口等待客人(监听端口)
    ├─ 接待客人进门(接收请求)
    ├─ 理解客人需求(解析HTTP)
    ├─ 转告厨房(传给你的代码)
    ├─ 接收厨房做好的菜(接收响应)
    └─ 送给客人(发送响应)
​
你的业务代码 = 厨房(处理业务逻辑)

1.4 技术架构中的位置

客户端(浏览器/APP)
    ↓ HTTP 请求
[Kestrel] ← 这是网络边界
    ↓
[ASP.NET Core 请求管道]
    ├─ 路由
    ├─ 认证
    ├─ 授权
    └─ 中间件
        ↓
    [你的控制器/代码]
        ↓ 返回结果
[ASP.NET Core 管道处理]
    ↓
[Kestrel]
    ↓ HTTP 响应
客户端

1.5 代码中的 Kestrel

var builder = WebApplication.CreateBuilder(args);
​
builder.Services.AddControllers();
​
var app = builder.Build();
​
app.MapControllers();
​
app.Run();  // ← 这行代码启动 Kestrel

当执行 app.Run() 时:

1. 托管系统启动
2. Kestrel 被初始化
3. Kestrel 绑定到指定的网络端口
4. Kestrel 开始"监听"
5. 控制台输出:Now listening on: http://localhost:5000
6. 程序进入等待状态,不会退出
7. 每当有 HTTP 请求到来,Kestrel 接收并处理

2. 为什么叫"监听"

2.1 "监听"的含义

监听(Listen)= 在网络端口上等待连接

这是网络编程的标准术语。

2.2 底层原理

// Kestrel 底层做的事情(简化版)
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
​
// 绑定到端口
socket.Bind(new IPEndPoint(IPAddress.Any, 5000));
​
// 开始监听(Listen)
socket.Listen(100);  // ← 这就是"监听"// 等待客户端连接
while (true)
{
    Socket client = socket.Accept();  // 阻塞等待
    // 处理客户端请求...
}
​
​

网络通信的基本原理:

客户端(浏览器)                    服务器(你的程序)
      |                                    |
      | 1. 我要连接 192.168.1.100:5000     |
      |--------------------------------→   |
      |                                    | 2. 检查:有程序在监听 5000 端口吗?
      |                                    |    - 有 → 接受连接
      |                                    |    - 没有 → 拒绝连接
      |   3.---------------------------- |
      |        连接建立                     |

如果没有监听:

客户端连接  服务器 5000 端口  没有程序监听  连接失败
浏览器显示:ERR_CONNECTION_REFUSED(连接被拒绝)

2.3 "监听"的三个步骤

1. Bind(绑定)
   - Kestrel 告诉操作系统:"我要用 5000 端口"
   - 操作系统分配端口给 Kestrel

2. Listen(监听)
   - Kestrel 告诉操作系统:"开始接收这个端口的连接"
   - 操作系统将到达该端口的请求放入队列

3. Accept(接受)
   - Kestrel 从队列中取出连接
   - 开始处理 HTTP 请求

2.4 为什必须"监听"

网络通信的基本规则:

客户端要连接服务器,必须知道:
1. 服务器的 IP 地址
2. 服务器的端口号

服务器要接受连接,必须:
1. 在指定端口上"监听"
2. 等待客户端连接

示例:

用户在浏览器输入:http://192.168.1.100:5000/api/users

浏览器做的事:
1. 解析域名/IP:192.168.1.100
2. 解析端口:5000
3. 向 192.168.1.100 的 5000 端口发起 TCP 连接

服务器端(Kestrel):
1. 必须已经在 5000 端口上"监听"
2. 才能接收到这个连接
3. 如果没有监听 5000 端口 → 连接失败

2.5 查看监听状态

Windows:

netstat -ano | findstr :5000
# 输出:TCP    0.0.0.0:5000    0.0.0.0:0    LISTENING    12345
#              ↑                              ↑
#           监听端口                       监听状态

Linux:

netstat -tuln | grep :5000
# 或
ss -tuln | grep :5000

2.6 监听范围

// 只监听本机回环接口
builder.WebHost.UseUrls("http://localhost:5000");
// 或
builder.WebHost.UseUrls("http://127.0.0.1:5000");
// 结果:只有本机可以访问

// 监听所有网络接口
builder.WebHost.UseUrls("http://*:5000");
// 或
builder.WebHost.UseUrls("http://0.0.0.0:5000");
// 结果:任何能到达服务器的客户端都可以访问

// 监听指定网络接口
builder.WebHost.UseUrls("http://192.168.1.100:5000");
// 结果:只能通过这个 IP 访问

3. Kestrel 的真实工作

3.1 核心职责

Kestrel = 系统的 HTTP 服务处理引擎

Kestrel 的工作内容:

1. 网络层
   ├─ 绑定端口
   ├─ 监听连接
   ├─ 接受 TCP 连接
   └─ 管理连接池

2. HTTP 协议层
   ├─ 解析 HTTP 请求(请求行、请求头、请求体)
   ├─ 支持 HTTP/1.1
   ├─ 支持 HTTP/2
   ├─ 支持 HTTP/3(QUIC)
   └─ 组装 HTTP 响应

3. 数据流转
   ├─ 将 HTTP 请求转换为 HttpContext
   ├─ 传递给 ASP.NET Core 管道
   ├─ 接收管道返回的响应
   └─ 发送给客户端

4. 连接管理
   ├─ Keep-Alive 连接复用
   ├─ 超时处理
   ├─ 连接限制
   └─ 优雅关闭

3.2 请求处理全流程

客户端发送:GET /api/users HTTP/1.1

[Kestrel 接收]
    ↓
1. 接收 TCP 数据流
2. 解析 HTTP 协议
   - 请求方法:GET
   - 路径:/api/users
   - 协议版本:HTTP/1.1
   - 请求头:Host, User-Agent, Accept...
3. 创建 HttpContext 对象
   - HttpContext.Request.Method = "GET"
   - HttpContext.Request.Path = "/api/users"
   - HttpContext.Request.Headers = [...]
    ↓
[传递给 ASP.NET Core 管道][路由中间件] → 匹配到控制器
[认证中间件] → 验证身份
[授权中间件] → 检查权限
[控制器执行] → 返回数据
    ↓
[管道返回响应][Kestrel 接收响应]
    ↓
4. 组装 HTTP 响应
   HTTP/1.1 200 OK
   Content-Type: application/json
   Content-Length: 123
   
   {"users": [...]}
5. 发送 TCP 数据流
    ↓
客户端接收响应

3.3 代码验证

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

// 所有请求都经过 Kestrel
app.MapGet("/api/users", () => 
{
    return new[] { "User1", "User2" };
});

app.MapPost("/api/users", (User user) => 
{
    // Kestrel 已经将请求体反序列化为 User 对象
    return Results.Created($"/api/users/{user.Id}", user);
});

app.Run();
// Kestrel 启动,监听端口
// 所有 /api/users 的请求都由 Kestrel 接收和处理

3.4Kestrel 构建的完整 HTTP 服务

从网络字节到你的代码:

1. 客户端发送原始字节流
   ↓
   47 45 54 20 2f 61 70 69 2f 75 73 65 72 73 20 48 54 54 50 ...
   (这是 "GET /api/users HTTP/1.1..." 的二进制)
   ↓

2. Kestrel 接收字节流
   ↓

3. Kestrel 解析为 HTTP 请求
   ┌─────────────────────────┐
   │ Method: GET             │
   │ Path: /api/users        │
   │ Protocol: HTTP/1.1      │
   │ Headers:                │
   │   Host: localhost:5000  │
   │   User-Agent: Chrome    │
   │   Accept: application/json │
   └─────────────────────────┘
   ↓

4. Kestrel 构建 HttpContext 对象
   HttpContext {
     Request: {
       Method: "GET",
       Path: "/api/users",
       Headers: {...}
     },
     Response: {
       StatusCode: 200,
       Headers: {...},
       Body: ...
     }
   }
   ↓

5. 传递给 ASP.NET Core 管道
   ↓

6. 你的代码处理
   app.MapGet("/api/users", () => new[] { "User1", "User2" });
   ↓

7. 返回结果给 Kestrel
   return new[] { "User1", "User2" };
   ↓

8. Kestrel 组装 HTTP 响应
   HTTP/1.1 200 OK
   Content-Type: application/json
   Content-Length: 28
   
   ["User1","User2"]
   ↓

9. Kestrel 转换为字节流
   48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b ...
   ↓

10. 发送给客户端

你的代码只需要:

app.MapGet("/api/users", () => new[] { "User1", "User2" });

Kestrel 帮你做了所有底层工作!

3.5 Kestrel 构建的 HTTP 能力

HTTP/1.1 支持
// Kestrel 自动支持
// - Keep-Alive 连接复用
// - 分块传输编码
// - 管道化请求
HTTP/2 支持
builder.WebHost.ConfigureKestrel(options =>
{
    options.Listen(IPAddress.Any, 5001, listenOptions =>
    {
        listenOptions.UseHttps();
        listenOptions.Protocols = HttpProtocols.Http2;
    });
});

// 支持:
// - 多路复用
// - 服务器推送
// - 头部压缩
HTTP/3 支持 (QUIC)
builder.WebHost.ConfigureKestrel(options =>
{
    options.Listen(IPAddress.Any, 5001, listenOptions =>
    {
        listenOptions.UseHttps();
        listenOptions.Protocols = HttpProtocols.Http3;
    });
});
WebSocket 支持
app.UseWebSockets();

app.Map("/ws", async context =>
{
    if (context.WebSockets.IsWebSocketRequest)
    {
        var webSocket = await context.WebSockets.AcceptWebSocketAsync();
        // Kestrel 处理 WebSocket 协议升级
    }
});
HTTPS/TLS 支持
builder.WebHost.ConfigureKestrel(options =>
{
    options.Listen(IPAddress.Any, 5001, listenOptions =>
    {
        listenOptions.UseHttps("cert.pfx", "password");
        // Kestrel 处理 TLS 握手和加密
    });
});

3.6 Kestrel 不做什么

❌ 路由匹配(由路由中间件做)
❌ 身份验证(由认证中间件做)
❌ 授权检查(由授权中间件做)
❌ 业务逻辑(由你的代码做)
❌ 数据库操作(由你的代码做)
❌ 静态文件服务(由静态文件中间件做)

✅ Kestrel 只负责 HTTP 协议层的事情


有了 Kestrel,你的程序:

- ✅ 成为一个 Web 服务器
- ✅ 可以处理 HTTP/HTTPS 请求
- ✅ 支持 HTTP/1.1, HTTP/2, HTTP/3
- ✅ 可以对外提供 API/网站服务

4. 系统主地址概念

4.1 什么是"系统主地址"

系统主地址 = Kestrel 监听的地址 = 整个应用的网络入口

builder.WebHost.UseUrls("http://localhost:5000");
//                       ↑
//                  这就是系统主地址

4.2 为什么叫"主地址"

因为所有功能都基于这个地址:

Kestrel 监听:http://localhost:5000
                      ↓
所有请求都通过这个地址进入:

- API 接口:       http://localhost:5000/api/users
- Swagger UI:     http://localhost:5000/swagger
- 健康检查:       http://localhost:5000/health
- 静态文件:       http://localhost:5000/images/logo.png
- SignalR Hub:    http://localhost:5000/chatHub

这是唯一的入口! 就像一栋楼只有一个大门。

4.3 配置主地址的方式

方式1:UseUrls(代码)
var builder = WebApplication.CreateBuilder(args);

// 配置主地址
builder.WebHost.UseUrls("http://localhost:8000");

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

// Kestrel 监听:http://localhost:8000
// 系统主地址:http://localhost:8000
方式2:appsettings.json
{
  "Urls": "http://localhost:8000"
}
var builder = WebApplication.CreateBuilder(args);
// ASP Net Core默认 appsettings.json 中的 "Urls"关键字

var app = builder.Build();
app.Run();
方式3:环境变量
export ASPNETCORE_URLS="http://localhost:8000"
dotnet MyApp.dll
方式4:命令行
dotnet MyApp.dll --urls "http://localhost:8000"

4.4 主地址的范围

// 只监听本地(开发环境)
"http://localhost:5000"
// 只有本机可以访问 http://localhost:5000

// 监听所有网卡(生产环境)
"http://*:5000"
// 可以通过服务器任何IP访问:
// - http://localhost:5000
// - http://192.168.1.100:5000
// - http://服务器公网IP:5000

// 监听指定IP
"http://192.168.1.100:5000"
// 只能通过这个IP访问

4.5 多个主地址

// 同时监听 HTTP 和 HTTPS
builder.WebHost.UseUrls(
    "http://localhost:5000",   // HTTP
    "https://localhost:5001"   // HTTPS
);

// 系统有两个主地址:
// - http://localhost:5000
// - https://localhost:5001

5. 编辑工具的地址

5.1 什么是"编辑工具的地址"

编辑工具 = IDE(Visual Studio / Rider / VS Code)

编辑工具的地址 = launchSettings.json 中配置的地址

5.2 launchSettings.json

位置: Properties/launchSettings.json

{
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5000;https://localhost:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

5.3 工作原理

当你在 IDE 中按 F5 启动时:

1. IDE 读取 launchSettings.json
2. 找到选中的 profile(如 "https")
3. 读取 applicationUrl
4. IDE 执行命令:
   dotnet run --urls "http://localhost:5000;https://localhost:5001"
5. 命令行参数传递给程序
6. WebHost 接收参数
7. Kestrel 监听这些地址

5.4 launchSettings.json 的特点

✅ 只在 IDE 中运行时生效
✅ 方便开发调试
✅ 可以配置多个 profile(如 http, https, Docker)

❌ 发布后不存在这个文件
❌ 直接运行 dotnet MyApp.dll 时不读取
❌ 部署到服务器时不生效

5.5 验证

测试1:IDE 运行

按 F5 启动
→ 使用 launchSettings.json 的地址
→ 监听 http://localhost:5000

测试2:命令行运行

dotnet run
→ 也会读取 launchSettings.json(如果存在)
→ 监听 http://localhost:5000

测试3:发布后运行

dotnet publish -c Release
cd bin/Release/net8.0/publish
dotnet MyApp.dll
→ launchSettings.json 不存在
→ 使用默认地址 http://localhost:5000

5.6 编辑工具地址 vs 主地址

概念配置位置作用范围优先级
编辑工具地址launchSettings.jsonIDE 开发时
系统主地址UseUrls/Urls/环境变量所有环境

如果同时配置:

// launchSettings.json
"applicationUrl": "http://localhost:5000"

// Program.cs
builder.WebHost.UseUrls("http://localhost:8000");

结果:Kestrel 监听 8000(UseUrls 优先级更高)


6. 不同部署场景的地址配置

场景Kestrel 监听地址外部访问地址Kestrel 角色
本地开发(IDE)localhost:5000localhost:5000监听 + 构建
本地开发(局域网)*:5000192.168.x.x:5000监听 + 构建
Linux 直接部署*:80服务器IP:80监听 + 构建
Nginx 反向代理localhost:5000域名:443监听 + 构建
IIS In-Process不适用IIS地址❌ 不使用
IIS Out-of-Process随机端口IIS地址监听 + 构建
Docker0.0.0.0:80容器映射端口监听 + 构建
Kubernetes0.0.0.0:80Service地址监听 + 构建

6.1 场景1:本地开发(IDE)

目标: 只有开发者自己访问

配置:

// launchSettings.json
{
  "profiles": {
    "Development": {
      "applicationUrl": "http://localhost:5000"
    }
  }
}

特点:

  • 只监听 localhost
  • 外部无法访问
  • 安全

访问:

开发者访问:http://localhost:5000 ✅
同事访问:  http://你的电脑IP:5000 ❌ 无法访问

6.2 场景2:本地开发(允许局域网访问)

目标: 让同事/测试人员访问

配置:

var builder = WebApplication.CreateBuilder(args);

if (builder.Environment.IsDevelopment())
{
    // 监听所有网卡
    builder.WebHost.UseUrls("http://*:5000");
}

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

访问:

你自己:     http://localhost:5000 ✅
同事:       http://192.168.1.100:5000 ✅
外网用:   ❌ 无法访问(局域网内)

6.3 场景3:Linux 服务器直接部署

目标: 程序直接暴露在公网

配置:

// appsettings.Production.json
{
  "Urls": "http://*:80"
}
# 部署
dotnet MyApp.dll
# Kestrel 监听 80 端口

架构:

用户浏览器
    ↓
http://47.103.25.88:80
    ↓
Kestrel 监听 0.0.0.0:80
    ↓
你的程序

问题:

  • ❌ 没有 HTTPS(不安全)
  • ❌ 端口直接暴露
  • ❌ 无法负载均衡

6.4 场景4:Nginx 反向代理(推荐)

目标: 生产环境标准部署

架构:

用户浏览器
    ↓
https://myapp.com (443端口)Nginx (处理 HTTPS, 负载均衡)
    ↓
http://localhost:5000 (内网)
    ↓
Kestrel 监听 localhost:5000
    ↓
你的程序

Nginx 配置: /etc/nginx/sites-available/myapp

server {
    listen 80;
    server_name myapp.com;
    
    # HTTP 重定向到 HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name myapp.com;
    
    # SSL 证书
    ssl_certificate /etc/ssl/certs/myapp.crt;
    ssl_certificate_key /etc/ssl/private/myapp.key;
    
    location / {
        # 转发到 Kestrel
        proxy_pass http://localhost:5000;
        
        # 传递真实客户端信息
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Kestrel 配置:

// appsettings.Production.json
{
  "Urls": "http://localhost:5000"
}
// Program.cs
var builder = WebApplication.CreateBuilder(args);

// 配置转发头(重要!)
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = 
        ForwardedHeaders.XForwardedFor | 
        ForwardedHeaders.XForwardedProto;
});

var app = builder.Build();

// 使用转发头中间件
app.UseForwardedHeaders();

app.Run();

地址对应关系:

层级监听地址说明
用户访问https://myapp.com域名 + HTTPS
Nginx 监听0.0.0.0:443监听所有IP的443端口
Nginx 转发http://localhost:5000转发到本机5000端口
Kestrel 监听http://localhost:5000只监听本机5000端口

必须匹配: Nginx 转发地址 = Kestrel 监听地址


6.5 场景5:IIS 托管(Windows)

模式A:In-Process(进程内)

架构:

用户请求
    ↓
IIS (80/443端口)
    ↓
你的程序(运行在IIS进程内)
    ↓
不使用 Kestrel ❌

web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" 
           modules="AspNetCoreModuleV2" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" 
                arguments=".\MyApp.dll" 
                stdoutLogEnabled="false" 
                hostingModel="inprocess">
      <!--        ↑ In-Process 模式 -->
    </aspNetCore>
  </system.webServer>
</configuration>

Program.cs:

var builder = WebApplication.CreateBuilder(args);

// UseUrls 会被忽略
// builder.WebHost.UseUrls("..."); // ← 无效

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

特点:

  • ❌ Kestrel 不工作
  • ✅ IIS 直接处理 HTTP
  • ✅ 性能最好
  • ❌ 只能 Windows

模式B:Out-of-Process(进程外)

架构:

用户请求
    ↓
IIS (80/443端口)
    ↓
转发到 http://localhost:随机端口
    ↓
Kestrel 监听(独立进程)
    ↓
你的程序

web.config:

<aspNetCore processPath="dotnet" 
            arguments=".\MyApp.dll" 
            hostingModel="outofprocess">
<!--        ↑ Out-of-Process 模式 -->
</aspNetCore>

Program.cs:

var builder = WebApplication.CreateBuilder(args);

// IIS 会自动设置端口,不需要手动配置
// builder.WebHost.UseUrls("..."); // 可选

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

特点:

  • ✅ 使用 Kestrel
  • ✅ IIS 转发请求
  • ✅ 程序独立进程

6.6 场景6:Docker 容器

Dockerfile:

FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY publish/ .

# 设置环境变量
ENV ASPNETCORE_URLS=http://+:80

EXPOSE 80

ENTRYPOINT ["dotnet", "MyApp.dll"]

或在 Program.cs 配置:

var builder = WebApplication.CreateBuilder(args);

// Docker 中必须监听 0.0.0.0
builder.WebHost.UseUrls("http://0.0.0.0:80");

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

运行:

docker build -t myapp .
docker run -d -p 8080:80 myapp

# 容器内:Kestrel 监听 0.0.0.0:80
# 宿主机:映射到 8080 端口
# 访问:http://localhost:8080

6.7 场景7:Kubernetes

Deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        ports:
        - containerPort: 80
        env:
        - name: ASPNETCORE_URLS
          value: "http://+:80"
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: myapp

架构:

用户请求
    
LoadBalancer (公网IP)
    
Service (ClusterIP)
    
Pod 1: Kestrel 监听 0.0.0.0:80
Pod 2: Kestrel 监听 0.0.0.0:80
Pod 3: Kestrel 监听 0.0.0.0:80

7. 完整配置示例

7.1 开发环境配置

// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// 开发环境配置
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
    
    // 开发时不需要配置 UseUrls
    // 使用 launchSettings.json 的配置即可
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

launchSettings.json:

JSON

{
  "profiles": {
    "https": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5000;https://localhost:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

7.2 生产环境配置(Nginx)

appsettings.Production.json:

JSON

{
  "Urls": "http://localhost:5000",
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

Program.cs:

C#

var builder = WebApplication.CreateBuilder(args);

// 配置服务
builder.Services.AddControllers();

// 配置转发头(Nginx 反向代理必需)
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = 
        ForwardedHeaders.XForwardedFor | 
        ForwardedHeaders.XForwardedProto;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

var app = builder.Build();

// 使用转发头
app.UseForwardedHeaders();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

Nginx 配置:

Nginx

server {
    listen 443 ssl;
    server_name myapp.com;
    
    ssl_certificate /etc/ssl/certs/myapp.crt;
    ssl_certificate_key /etc/ssl/private/myapp.key;
    
    location / {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

7.3 根据环境自动配置

C#

var builder = WebApplication.CreateBuilder(args);

// 根据环境配置监听地址
if (builder.Environment.IsDevelopment())
{
    // 开发:使用 launchSettings.json
}
else if (builder.Environment.IsProduction())
{
    // 生产:从配置文件读取
    // 或明确指定
    builder.WebHost.UseUrls("http://localhost:5000");
}

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

7.4 详细的 Kestrel 配置

C#

builder.WebHost.ConfigureKestrel(options =>
{
    // 监听配置
    options.Listen(IPAddress.Loopback, 5000);  // HTTP
    options.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("cert.pfx", "password");  // HTTPS
    });
    
    // 性能限制
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxConcurrentUpgradedConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024 * 1024; // 10MB
    options.Limits.MinRequestBodyDataRate = new MinDataRate(
        bytesPerSecond: 100, 
        gracePeriod: TimeSpan.FromSeconds(10)
    );
    
    // 超时设置
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    options.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(30);
});

总结

Kestrel 核心要点

  1. Kestrel 是什么

    • ASP.NET Core 内置的 HTTP 服务器
    • 负责处理所有 HTTP 请求和响应
  2. 为什么叫监听

    • 在网络端口上等待连接
    • 网络编程的标准术语
  3. 系统主地址

    • Kestrel 监听的地址
    • 整个应用的网络入口
    • 所有功能都基于这个地址
  4. 编辑工具地址

    • launchSettings.json 中的配置
    • 只在 IDE 开发时生效
    • 优先级低于代码配置
  5. 部署场景

    • 开发:localhost,安全隔离
    • 直接部署:0.0.0.0,监听所有IP
    • 反向代理:localhost,内网监听
    • IIS:In-Process 不用 Kestrel,Out-of-Process 用 Kestrel
    • Docker/K8s:0.0.0.0:80

关键配置

C#

// 监听地址配置(五选一)
builder.WebHost.UseUrls("http://localhost:5000");        // 代码
"Urls": "http://localhost:5000"                          // appsettings.json
ASPNETCORE_URLS=http://localhost:5000                    // 环境变量
dotnet run --urls "http://localhost:5000"                // 命令行
"applicationUrl": "http://localhost:5000"                // launchSettings.json

最佳实践

  • ✅ 开发:使用 launchSettings.json
  • ✅ 生产:使用 appsettings.json 或环境变量
  • ✅ 反向代理:配置转发头中间件
  • ✅ Docker:监听 0.0.0.0
  • ✅ 安全:生产环境使用 Nginx/IIS 做反向代理