Explorar o código

!698 解决在分布式部署情况下SignalR负载均衡问题。使用SignalRredis做底板支撑
Merge pull request !698 from jason0x1/next

zuohuaijun %!s(int64=2) %!d(string=hai) anos
pai
achega
26dd3500e3

+ 8 - 0
Admin.NET/Admin.NET.Application/Configuration/SignalRRedisDock.json

@@ -0,0 +1,8 @@
+{
+    "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
+
+  "SignalRRedisDock": {
+    "Enabled": false,
+    "RedisConnectionString": "127.0.0.1:6379,connectRetry=3,syncTimeout=1000,connectTimeout=1000,defaultDatabase=2,ssl=false,writeBuffer=10240,abortConnect=False" // Redis连接字符串
+  }
+}

+ 3 - 1
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
@@ -15,6 +15,8 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="7.0.5" />
+	<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="6.0.16" />
     <PackageReference Include="AngleSharp" Version="1.0.1" />
     <PackageReference Include="AspectCore.Extensions.Reflection" Version="2.3.0" />
     <PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />

+ 67 - 0
Admin.NET/Admin.NET.Core/Hub/SignalRDockExtensions.cs

@@ -0,0 +1,67 @@
+using StackExchange.Redis;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Admin.NET.Core;
+public static class SignalRDockExtensions
+{
+    /// <summary>
+    /// 注入redis底板
+    /// </summary>
+    /// <param name="services"></param>
+    /// <param name="delegateRedisConnectionString"></param>
+    /// <exception cref="ArgumentNullException"></exception>
+    public static void AddSignalR_RedisDock(this IServiceCollection services, Func<string> delegateRedisConnectionString)
+    {
+        var RedisConnectionString = delegateRedisConnectionString();
+        if (string.IsNullOrEmpty(RedisConnectionString))
+        {
+            throw new ArgumentNullException(nameof(RedisConnectionString));
+        }
+        services.AddSignalR(hubOptions =>
+        {
+            //SignalR 自己的 pinger ,客户端在定义的时间跨度内没有响应,它将触发OnDisconnectedAsync
+            hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(5);
+        }).AddJsonProtocol()
+            .AddMessagePackProtocol()
+            // 支持MessagePack
+            .AddStackExchangeRedis(options =>
+            {
+                options.ConnectionFactory = async writer =>
+                {
+
+                    var config = new ConfigurationOptions
+                    {
+                        AbortOnConnectFail = false,
+                        // Password = "changeme",
+                        ChannelPrefix = "__signalr_",
+                    };
+                    //config.EndPoints.Add(IPAddress.Loopback, 0);
+                    //config.SetDefaultPorts();
+                    config.DefaultDatabase = 1;
+                    var connection = await ConnectionMultiplexer.ConnectAsync(RedisConnectionString, writer);
+                    connection.ConnectionFailed += (_, e) =>
+                    {
+                        ConsoleDebug.WriteLine("Connection to Redis failed.");
+                    };
+
+                    if (connection.IsConnected)
+                    {
+                        ConsoleDebug.WriteLine("connected to Redis.");
+                    }
+                    else
+                    {
+                        ConsoleDebug.WriteLine("Did not connect to Redis");
+                    }
+
+                    return connection;
+                };
+            });
+    }
+}
+
+
+//redis查看订阅列表 PUBSUB CHANNELS

+ 5 - 0
Admin.NET/Admin.NET.Web.Core/Startup.cs

@@ -34,6 +34,11 @@ public class Startup : AppStartup
         services.AddSqlSugar();
         // JWT
         services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
+        if (App.GetConfig<bool>("SignalRRedisDock:Enabled"))
+        {
+            //redis底板 AddSignalR_RedisDock 需要在Addjwt后。在之前会导致JwtHandler失效
+            services.AddSignalR_RedisDock(() => App.GetConfig<string>("SignalRRedisDock:RedisConnectionString"));
+        }
         // 允许跨域
         services.AddCorsAccessor();
         // 远程请求