You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Nginx作为带SignalR Hub的Blazor Server反向代理

解决Blazor Server+SignalR Hub的Nginx反向代理504超时问题

核心问题分析

从日志来看,ASP.NET已完成首页请求的业务处理,但未向Nginx返回响应,最终导致Nginx超时。这大概率是Blazor Server自身依赖的SignalR连接(用于双向通信)未正确建立,加上自定义Hub的配置缺失,导致请求挂起。以下是针对性的解决方案:


一、修正Nginx完整配置

将WebSocket升级、长连接超时、流式响应适配等关键配置整合,确保同时兼容Blazor Server内置SignalR和自定义Hub:

http {
    # 全局WebSocket升级映射,必须放在server块外部
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    # HTTP跳转HTTPS及Certbot验证
    server {
        listen 80;
        server_name example.com *.example.com;
        server_tokens off;

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }

        location / {
            return 301 https://$host$request_uri;
        }
    }

    # HTTPS主服务配置
    server {
        listen 443 ssl;
        server_name example.com *.example.com;
        server_tokens off;

        ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        include             /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam         /etc/letsencrypt/ssl-dhparams.pem;

        # 全局反向代理基础配置
        proxy_http_version 1.1;
        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;
        proxy_read_timeout 300s; # 延长超时适配SignalR长连接
        proxy_buffering off; # 禁用缓冲,适配Blazor流式响应

        # Blazor Server主路径配置
        location / {
            proxy_pass http://docker-service-name:5000;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }

        # 自定义SignalR Hub单独配置
        location /notifications {
            proxy_pass http://docker-service-name:5000;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_cache off; # 强制禁用Hub请求缓存
        }
    }
}

二、ASP.NET应用配置修正

在Program.cs中添加反向代理头转发配置,确保Blazor和SignalR能正确识别外部请求的协议和地址:

builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    // 允许Docker桥接网络的IP段(根据实际网络调整)
    options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.17.0.0"), 16));
    options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.18.0.0"), 16));
});

// 必须放在UseRouting、UseHttpsRedirection之前
app.UseForwardedHeaders();

// 原有的SignalR和响应压缩配置保持不变
builder.Services.AddSignalR();
builder.Services.AddResponseCompression(opts =>
{
    opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
        ["application/octet-stream"]);
});
app.UseResponseCompression();
app.MapHub<NotificationHub>(NotificationHub.HubUrl);

三、Razor页面Hub连接容错处理

添加错误捕获和重连逻辑,便于排查生产环境的连接问题:

@implements IAsyncDisposable

@code {
    private HubConnection _hubConnection;

    public async ValueTask DisposeAsync()
    {
        Log.Debug("Page {Page} disposing", nameof(Home));
        await _hubConnection.DisposeAsync();
    }
    
    protected override async Task OnInitializedAsync()
    {
        Log.Debug("Page {Page} initialized", nameof(Home));

        _hubConnection = new HubConnectionBuilder()
            .WithUrl(NavigationManager.ToAbsoluteUri(NotificationHub.HubUrl))
            .Build();
        
        _hubConnection.On<InviteCreatedNotification>(NotificationHub.InviteCreatedMethod, HandleInviteCreated);
        _hubConnection.On<InviteAcceptedNotification>(NotificationHub.InviteAcceptedMethod, HandleInviteAccepted);

        // 添加断开重连逻辑
        _hubConnection.Closed += async (error) =>
        {
            Log.Error(error, "Hub connection closed");
            await Task.Delay(5000);
            await _hubConnection.StartAsync();
        };

        try
        {
            await _hubConnection.StartAsync();
            Log.Debug("Hub connected successfully");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "Failed to connect to hub");
        }
    }
    
    private void HandleInviteCreated(InviteCreatedNotification notification)
    {
        Log.Debug("{Notification} received", nameof(InviteCreatedNotification));
    }
    
    private void HandleInviteAccepted(InviteAcceptedNotification notification)
    {
        Log.Debug("{Notification} received", nameof(InviteAcceptedNotification));
    }
}

四、排查验证步骤

  1. 容器连通性检查:在Nginx容器内执行curl -v http://docker-service-name:5000/,确认能获取完整响应,排除网络连通问题。
  2. ASP.NET日志验证:检查是否有Request finished结尾日志,确认请求是否真的处理完成。
  3. 浏览器网络排查:查看控制台的/_blazor(Blazor内置SignalR)和/notifications请求,确认WebSocket升级是否成功(状态码101)。

内容的提问来源于stack exchange,提问作者orderlyfashion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:11:03