起因:

 ASP.NET Core SignalR是一个开源库,可简化向应用添加实时 SignalR Web 功能。 实时 Web 功能使服务器端代码能够立即将内容推送到客户端。(相信大家都用得比较多了)

 在应用过程中,出现某些异常断开连接情况,那么如何处理客户端自动重连呢?

问题现象:

 服务器因某些特殊原因,导致服务停止一段时间后;当服务端重启后,Signalr连接的客户端未能自动连接到服务上。

解决办法:

  实现自动断线重连的2种方式:

  • 在onClose事件中手动重新创建连接:
connection.Closed += async (error) =>
{
    //等待3s后重新创建连接
    await Task.Delay(3* 1000);
    await connection.StartAsync();
};
  • 将配置为使用方法 WithAutomaticReconnect 自动重新连接

  重连规则:

  1、WithAutomaticReconnect在没有任何参数的情况下, 将客户端配置为分别等待0、2、10 和 30 秒,然后尝试每次重新连接尝试,在四次尝试失败后停止。出发Closed事件

HubConnectionBuilder hubConnectionBuilder = new HubConnectionBuilder();
hubConnectionBuilder.WithUrl(url, options => { });
//重连
hubConnectionBuilder = (HubConnectionBuilder)hubConnectionBuilder
    .WithAutomaticReconnect();
//创建连接对象
hubConnection = hubConnectionBuilder.Build();
//断开连接
hubConnection.Closed += HubConnection_Closed;
//重连中
hubConnection.Reconnecting += HubConnection_Reconnecting;
//重连成功
hubConnection.Reconnected += HubConnection_Reconnected;
//心跳检查
hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(60);

  2、指定断线重连参数:连接规则同上(次数变成指定的3次)

//指定重连间隔:0s,0s,10s
HubConnection connection= new HubConnectionBuilder() .WithUrl(new Uri("http://127.0.0.1:5000/chathub")) .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.Zero, TimeSpan.FromSeconds(10) }) .Build();

  3、自定义重连规则使用:实现一直自动重连

HubConnectionBuilder hubConnectionBuilder = new HubConnectionBuilder();
hubConnectionBuilder.WithUrl(url, options => { });
//自定义重连规则实现
hubConnectionBuilder = (HubConnectionBuilder)hubConnectionBuilder
    .WithAutomaticReconnect(new RetryPolicy());

  重连规则实现:重连规则:重试次数<50:间隔1s;重试次数<250:间隔30s;重试次数>250:间隔1m

//实现IRetryPolicy接口
class RetryPolicy : IRetryPolicy
{
    /// <summary>
    /// 重连规则:重连次数<50:间隔1s;重试次数<250:间隔30s;重试次数>250:间隔1m
    /// </summary>
    /// <param name="retryContext"></param>
    /// <returns></returns>
    public TimeSpan? NextRetryDelay(RetryContext retryContext)
    {
        var count = retryContext.PreviousRetryCount / 50;
        if (count < 1)//重试次数<50,间隔1s
        {
            return new TimeSpan(0, 0, 1);
        }
        else if (count < 5)//重试次数<250:间隔30s
        {
            return new TimeSpan(0, 0, 30);
        }
        else //重试次数>250:间隔1m
        {
            return new TimeSpan(0, 1, 0);
        }
    }
} 

其他常见用法:

 1、服务端/客户端配置:

  a)Json序列化属性名不修改大小写:

services.AddSignalR()
    .AddJsonProtocol(options => {
        options.PayloadSerializerOptions.PropertyNamingPolicy = null;
    });

  b)服务端常用配置属性:

   属性配置使用方式:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR(hubOptions =>
    {
        hubOptions.EnableDetailedErrors = true;
        hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(1);
    });
}

   配置属性说明如下:


 2、如何提升Signalr传输性能:

  使用MessagePackc传输:MessagePack 是一种快速、精简的二进制序列化格式。 当性能和带宽需要考虑时,它很有用,因为它会创建比 JSON更小的消息。

  在查看网络跟踪和日志时,不能读取二进制消息,除非这些字节是通过 MessagePack 分析器传递的。 SignalR 提供对 MessagePack 格式的内置支持,并为客户端和服务器提供要使用的 Api。

  使用方式:添加包Microsoft.AspNetCore.SignalR.Protocols.MessagePack,在 Startup.ConfigureServices 方法中,将添加 AddMessagePackProtocol 到在 AddSignalR 服务器上启用 MessagePack 支持的调用

services.AddSignalR().AddMessagePackProtocol();

参考:

 https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction

06-14 00:08