Description
Summary
When using SignalR Backplane, in particular Redis Backplane, there is a cost in terms of bandwidth used and latency added by the backplane. The wasted bandwidth & latency is 1/N (N = Number of servers)
When the number of server is small, the cost is higher
Motivation and goals
This is my understanding of Redis SignalR Backplane. I'm 90% confident that I understood how it works, but I'm not 100% sure. Sorry if I got it totally wrong :)
- Whenever a message is sent to a group or all on SignalR with a backplane, the message is sent to Redis via
PUBLISH
. - Redis sends this message to both the sender and the other server indiscriminately
- If you have 2 servers, the message (Ex: 1kB) is sent to Redis once (1kB) and Redis sends it to 2 servers (2kB). So 50% bandwidth wasted. This ratio decreases with the number of servers (1/N)
- In the same scenario, if a user is connected to the sender server, then he has to wait for the PUB/SUB roundtrip before receiving the message.
The proposal is the following:
- Exclude the sender from receiving the message
- Send the message directly to users connected to the current server without paying the cost of a Redis PUB/SUB round trip
Benefits / Limits
Benefits are obvious in terms of wasted bandwidth & latency
However, it does not improve the "worst possible latency".
It only improves the average latency.
There is an added benefit that messages that needs to be broadcasted might benefit from the freed bandwidth
Design proposal
-
to exclude the sender from receiving the message, in a scenario where the server don't know the names of the other servers, we could use PSUBSCRIBE/PPUBLISH
Let's say you have a group named "TOY"
Servers could subscribe to this channel using^TOY(?!MACHINENAME1).*$
where MACHINENAME1 is the name of the current machine (there is probably some escaping to do to)
Fortunately, the current implementation of Redis backplane automatically switches to Pattern based PUB/SUB
See Add precision about wildcard (*) + Redis SignalR Backplane = Pattern based subscriptions AspNetCore.Docs#29435
So this part is already "possible" -
Then we must publish each message both to the Redis AND to the users connected to the current server
This is done by adapting the publish code. Probably around here:
https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/server/StackExchangeRedis/src/RedisHubLifetimeManager.cs#L298