Sending data to individual clients instead of using Clients. Everything in SignalR

annotation

Hi, I am working on an application that uses SignalR to send data updates to a client. Data access is controlled by permissions, each data record ( Item

) contains a link to one permission. Users are associated with roles, each role is associated with a set of permissions. Each given user is only allowed to see entries that reference the permissions that are in his (user) roles.

Example

Suppose you have 500 permissions on the system, randomly distributed among 50 roles, there are also 1000 users who are online and are randomly associated with the 50 roles that are defined on the system. Therefore, some users will have a unique set of permissions, and there may also be users who have the same set of roles and therefore the same set of permissions.

Suppose one of the users has changed records 800

, and each of these records will refer to one of the 500 permissions defined on the system.

Problem (Permissions cause data scatter among users)

Now, to inform users of this change, a message must be sent to every distinguished user that contains a set of records that the user is entitled to see. This means that depending on the set of permissions the user has, they can get either:

  • no entries and no notice at all if it does not have the appropriate permissions,
  • some partial number of entries (less than 800) if it only has a fraction of the permissions
  • all 800 entries if he has all the required permissions

Question

I will suffer from performance degradation if I send messages to each client separately:

var data = GetData();
var users = GetConnectedUsers();

foreach (var user in users)
{
    var filteredData = FilterByPermissions(user, data);

    foreach (var connectionId in user.Connections)
    {
        Clients.Client(connectionId).onData(filteredData);
    }
}

      

I've looked at the NodeJS socket.io implementation before and it did a normal foreach to send data, if I understand correctly than in SignalR Clients.All

under the hood, it does the same foreach loop I'm trying to do.

Can this be done? Instead of using Clients.All.onData(...)

? I read about some problems with this approach related to the case when the application is hosted in a WebFarm.

Will I benefit from using SignalR Groups? I think it is possible to put each user into groups based on the permissions they have. Wouldn't it be nice if the user is associated with 100-150 SignalR groups. If this is true, this will be a problem, because it is more profitable to send the entire collection of data to the user in one message, rather than breaking it down into 100-150 messages that are sent more efficiently through groups.

Thank you in advance!

Model diagram

Here is the link to the image

Image description

+3


source to share


1 answer


Your understanding of the correct handling of connections is correct; SignalR will handle each client connection individually and sequentially. Since it is based on HTTP, it cannot multicast.

Thus, in many cases, there will not be a large performance penalty when navigating through a list of clients versus using Clients.All

or Clients.Group(name)

. Groups are mostly a matter of convenience, so using your own implementation to address a subset of clients should be fine.



One difference is that if you are accessing each client individually, the data will get serialized every time, which can make a difference, especially if you are sending the same data with a lot of records to many users. So, depending on how many users you typically send and how long the data takes to serialize, you might be better off using groups. If the data is unique for each user and usually only one connection per user, then obviously it won't make any difference.

+1


source







All Articles