SignalR and large number of groups

2019-05-29 13:46发布

问题:

I'm using SignalR's latest version and it's great. However, I've recently hit an interesting scaling issue: it seems that SignalR sends all the client's groups from the client in the query string. My system requires that a person join numerous groups, which represent all the projects that the user is subscribed to, and receive notifications on any of them.

this large number of groups (and me using GUIDs for ids) has caused the querystring to reach its maximum size, and SignalR to stop working.

This is what Fiddler shows in the request webform (using long polling for the Azure bug):

transport   longPolling
connectionId    bbed6f35-8379-4be3-ac28-ef3e618382ae
connectionData  [{"name":"jethub"}]
messageId   85
groups  ["JetHub.f9f81bcc-8417-46bd-bae5-c4134972601d","JetHub.5139a8de-04c2-48da-9427-39666e52fabd","JetHub.6b12e333-4d22-47c3-8587-7a9ad5026184","JetHub.252ea279-7a71-40e7-b03c-7d63e69f07ab","JetHub.a4843a77-1e6d-4693-b3de-b392ef465410","JetHub.27feb53a-3c2d-4b11-92f7-dbdffb874b25","JetHub.8840dfcf-e6be-4b72-965b-b282a60446e8","JetHub.bf7d3301-6fc0-4499-bee8-fe22f1bc2281","JetHub.655cba0e-7f72-402c-b80b-dcb740546163","JetHub.85d817e2-67a3-4291-b564-5320598339f6","JetHub.e3079263-3f6e-4a54-ad88-0dfc5dd2ce18","JetHub.33f00a67-9b05-4293-8119-4617e2fed9b0","JetHub.6323cfe8-fb81-4716-b553-79b9d72641a5","JetHub.b4359f8a-030a-4ac9-aacd-c05b42163bcc", ... many more]

I know I can increase the querystring size in IIS, but is there a better way to manage groups, or should I try to create my server-side grouping scheme and broadcast to each client separately? can PersistenConnections help in that regard?

Thanks.

回答1:

As groups are roundtripped via the query string in SignalR 0.5.3, you have the following options: a) increase the maximum query string size b) use shorter group names c) handle grouping yourself on the server and broadcast seperately to each user

PersistentConnections won't help here as the Hub API is built on top of them, so you'll run into the same problem.



回答2:

I know that this has already been answered to your satisfaction, but there is a way of managing groups on the server without sending messages to each client individually. You can implement your own HubDispatcher:

using System.Collections.Generic;
using SignalR;
using SignalR.Hubs;

namespace My.Hubs
{
    public class MyHubDispatcher : HubDispatcher
    {
        public MyHubDispatcher() : base("/myhubs") { }

        protected override Connection CreateConnection(string connectionId, IEnumerable<string> signals, IEnumerable<string> groups)
        {
            //ex: IEnumerable<string> myGroups = new string[] { "MyHub.MyGroup", "MyHub.MyOtherGroup", "MyOtherHub.MyGroup" };
            IEnumerable<string> myGroups = GetGroups(connectionId);
            return base.CreateConnection(connectionId, signals, myGroups);
        }
    }
}

You can then set up routing like any other PersistentConnection:

using System.Web;
using System.Web.Routing;
using SignalR;

namespace My
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class Application : HttpApplication
    {
        protected void Application_Start()
        {
            RouteTable.Routes.MapConnection<Hubs.MyHubDispatcher>("myhubs", "myhubs/{*operation}");
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

Then you can use groups on you Hubs like you normally would:

using SignalR.Hubs;

namespace My.Hubs
{
    public class MyHub : Hub
    {
        public void AlertClients(string id, int duration)
        {
            Clients["MyGroup"].Alert("MyGroup");
            Clients["MyOtherGroup"].Alert("MyOtherGroup");
        }
    }
}

If you using the JS client you can simply include the script at ~/myhubs/hubs instead of ~/signalr/hubs. If you are using the .NET client you just use new Client.Hubs.HubConnection("http://foo/myhubs", useDefaultUrl: false);