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

Azure Web App配置SignalR Hub对接Azure SignalR服务的问题求助

问题排查:Azure SignalR Service 连接与组操作异常

问题描述

  • Hub无法稳定加载到Azure SignalR Service,报错与Serverless/Default模式相关,日志如下:
2023-02-16T14:05:25.034917571Z info: Microsoft.Azure.SignalR.Connections.Client.Internal.WebSocketsTransport[1]
2023-02-16T14:05:25.034960072Z       Starting transport. Transfer mode: Binary. Url: 'wss://nmg-opus-common-inventory-dev-sigr.service.signalr.net/server/?hub=myhub&cid=9e64b380-b752-4175-8fd2-215a2b62139d'.
2023-02-16T14:05:25.057819457Z info: Microsoft.Azure.SignalR.Connections.Client.Internal.WebSocketsTransport[11]
2023-02-16T14:05:25.057859557Z       WebSocket closed by the server. Close status NormalClosure.
2023-02-16T14:05:25.057865857Z info: Microsoft.Azure.SignalR.ServiceConnection[24]
2023-02-16T14:05:25.057870457Z       Connection to service '(Primary)https://nmg-opus-common-inventory-dev-sigr.service.signalr.net(hub=MyHub)' handshake failed, probably caused by network instability or service restart. Will retry after the back off period. Error detail: Azure SignalR Service is in serverless mode, server connection is not allowed.. Id: 9e64b380-b752-4175-8fd2-215a2b62139d
2023-02-16T14:05:25.057875657Z info: Microsoft.Azure.SignalR.Connections.Client.Internal.WebSocketsTransport[6]
2023-02-16T14:05:25.057880257Z       Transport is stopping.
  • 将服务设为Serverless模式时,客户端看似连接成功,但调用JoinGroup方法后无响应,连接是在Blazor页面点击元素后建立的。
  • 已尝试调整Azure设置、修改代码同步为异步等操作,问题仍未解决。

相关代码

SignalR Hub代码

public class MyHub : Hub
{
    public async Task SendMessage(string groupName, string message)
    {
        await Group(groupName).SendAsync("ReceiveMessage", message);
    }

    public async Task JoinGroup(string groupName)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
    }

    public async Task LeaveGroup(string groupName)
    {
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
    }

    public override async Task OnConnectedAsync()
    {
        await Clients.Client(Context.ConnectionId).SendAsync("Connected", Context.ConnectionId);
    }
}

Web App的Startup代码

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAzureAppConfiguration();
        services.AddSignalR(e => { e.MaximumReceiveMessageSize = 10240000; });

        string SignalRURLHub = Configuration.GetValue<string>("Resources:SignalR:Inventory:ConnectionString");
        services.AddSignalR().AddAzureSignalR(SignalRURLHub);
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseAzureAppConfiguration();
        app.UseRouting();

        var SignalRHubName = $"/{Configuration.GetValue<string>("Resources:SignalR:HubName")}";

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHub<MyHub>(SignalRHubName);
        });
    }
}

客户端连接初始化代码

protected HubConnection _connection;

private readonly string groupName;

protected ClientHandler(string connectionString, string hubName, string groupName, string userId = null)
{
    var serviceUtils = new ServiceUtils(connectionString);

    var url = GetClientUrl(serviceUtils.Endpoint, hubName);
    _connection = new HubConnectionBuilder()
        .WithUrl(url
        , option =>
        {
            option.AccessTokenProvider = () =>
            {
                return Task.FromResult(serviceUtils.GenerateAccessToken(url, userId));
            };
        })
        
        .WithAutomaticReconnect(new AlwaysRetryPolicy())
        .ConfigureLogging(logging =>
        {
            logging.SetMinimumLevel(LogLevel.Trace);
            logging.AddConsole();
        })
        .Build();
        
   this.groupName = groupName;
   _connection.Reconnected += JoinGroup;
   _connection.On("Connected", new[] { typeof(string) }, OnInitialConnection);
}

private string GetClientUrl(string endpoint, string hubName)
{
    return $"{endpoint}/client/?hub={hubName}";
}

private async Task JoinGroup(string contextId)
{
    try
    {
        await _connection.InvokeAsync("JoinGroup", groupName);  //JoinGroup is C# method name
    }
    catch (Exception e)
    {
    }
}

// Called separately after the ClientHandler object is created.
public async Task StartAsyncWithRetry(CancellationToken cancellationToken = default)
{
    while (!cancellationToken.IsCancellationRequested)
    {
        try
        {
             await _connection.StartAsync()
                .ContinueWith(res =>
            {
                _connection.InvokeAsync("JoinGroup", groupName);
            });

            if (_connection.State == HubConnectionState.Disconnected)
            {
                await Task.Delay(GetRandomDelayMilliseconds());
                continue;
            }

            return;
        }
        catch (Exception e)
        {
            await Task.Delay(GetRandomDelayMilliseconds());
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:35:26