在 Linux 或 Windows 下部署 ASP.NET Core 应用 时,通常使用 Kestrel 作为内置 Web 服务器,再通过 Nginx 做反向代理。
虽然官方文档推荐这种组合,但在实际操作中,常会遇到各种问题。本文记录我遇到的问题与解决方案。


一、基本配置回顾

1️⃣ Kestrel 启动示例(Program.cs)

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(5000); // Kestrel 监听 5000 端口
});

var app = builder.Build();
app.MapGet("/", () => "Hello World");
app.Run();

2️⃣ Nginx 反向代理配置示例

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass         http://127.0.0.1:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

✅ 这是最基本的反向代理配置。


二、常见问题及解决方法

问题 1:访问 Nginx 显示 502 Bad Gateway

原因分析:

  • Kestrel 未启动或端口未监听
  • 防火墙阻止 5000 端口
  • Nginx 配置的 proxy_pass 地址错误

解决方法:

  1. 确认 Kestrel 启动:
netstat -tulnp | grep 5000

  1. 确认防火墙允许端口:
sudo ufw allow 5000/tcp

  1. 检查 Nginx 配置语法并重启:
sudo nginx -t
sudo systemctl restart nginx


问题 2:HTTP 1.1 WebSocket 升级失败

原因分析:

  • WebSocket 需要 UpgradeConnection
  • Nginx 默认可能未转发这些头

解决方法:
在 Nginx 配置中加入:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";


问题 3:HTTPS 配置问题

  • Kestrel 通常监听 HTTP(5000)
  • Nginx 负责 HTTPS 终止
  • 如果直接用 HTTPS 到 Kestrel,证书配置可能复杂

解决方案:

  1. Kestrel 只监听 HTTP
  2. Nginx 配置 SSL 证书,并转发 HTTP 请求到 Kestrel

示例:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /etc/ssl/certs/example.crt;
    ssl_certificate_key /etc/ssl/private/example.key;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}


问题 4:获取客户端真实 IP

原因分析:

  • Kestrel 看到的都是 Nginx 的 IP
  • 需要使用 X-Forwarded-For

解决方法:

Program.cs 中添加:

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

并确保 Nginx 配置了:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;


问题 5:大文件上传失败或超时

原因分析:

  • Nginx 默认 client_max_body_size 为 1M
  • Kestrel 也有请求大小限制

解决方法:

  1. 修改 Nginx 配置:
server {
    ...
    client_max_body_size 50M;
}

  1. 修改 Kestrel 配置:
builder.WebHost.ConfigureKestrel(options =>
{
    options.Limits.MaxRequestBodySize = 50 * 1024 * 1024; // 50MB
});


三、部署优化建议

  1. 使用 Systemd 管理 Kestrel 服务
sudo nano /etc/systemd/system/kestrel-app.service

示例 Service 文件:

[Unit]
Description=Kestrel .NET App
After=network.target

[Service]
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/dotnet /var/www/myapp/MyApp.dll
Restart=always
RestartSec=10
SyslogIdentifier=kestrel-app
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production

[Install]
WantedBy=multi-user.target

  1. 开启 Nginx 缓存或压缩
    • 减少静态资源传输
    • 提升访问速度
  2. 日志监控
    • Kestrel 日志:dotnet MyApp.dll --urls http://*:5000
    • Nginx 日志:/var/log/nginx/access.log/var/log/nginx/error.log

四、总结

配置 Kestrel + Nginx 反向代理虽然官方推荐,但实际部署过程中常见问题包括:

问题原因解决方法
502 Bad GatewayKestrel 未启动 / Nginx 配置错误检查端口、重启服务
WebSocket 升级失败Upgrade/Connection 头未转发Nginx 配置 proxy_set_header
HTTPS 配置复杂Kestrel 直接 HTTPS 不方便让 Nginx 终止 SSL
客户端真实 IP 不可见未使用 X-Forwarded-For配置 ForwardedHeaders 中间件
大文件上传失败或超时Nginx & Kestrel 限制增加 client_max_body_size & MaxRequestBodySize

正确配置后,Kestrel + Nginx 能提供 高性能、稳定、安全的 .NET Core Web 服务