Can I avoid of using a SignalR backplane behind a load balancer? - signalr

I use SignalR in order to expose RabbitMQ messages to browsers. This works fine with one app instance obviously. The question is if it could work with multiple instances too without a backplane. I understand that SignalR client could be disconnected from the pod A and connected back to the pod B but what exactly is the issue here? I am fine to lose some messages during reconnection. Is it the only issue? Is reconnection to the pod B treated as a regular new connection so that the client is just subscribed again as it was subscribed normally without reconnection? Or the system doesn't have input parameters it had during initial subscription and therefore it cannot resubscribe without hints?

As long as all of your SignalR servers are getting the same data from RabbitMQ or getting only the data for the clients connected to them, you don't need a backplane.
You will need a backplane if you have one of the following:
Clients can communicate with one another.
One one SignalR server is connected to RabbitMQ but clients can connect to multiple SignalR servers.
SignalR servers are connected to different queues or getting different data from the same queue.
I have a similar setup with a database instead of RabbitMQ and need a backplane to either have only one of the SignalR servers access the database (and have data be sent to all clients) or to share the database load between servers (and have data be sent to all clients). This way, the server getting the data can have it sent to a client connected to a different server.
I am using SignalR for ASP.NET and the servers do not know who is subscribed to the other servers. All messages are sent over the backplane and each server determines if they apply to their connected clients. This works well with broadcasts for example or if the same user has multiple clients to make sure they all get the same data regardless of the server.

Related

Are there existing solutions for serving multiple websocket clients from a single upstream connection using a proxy server?

I have a data vendor for real-time data that has a strict limit on the number of websocket connections I am allowed to make to their API. I have multiple microservices that need to consume this data, with some overlap in subscriptions. The clients do not need to communicate back anything beyond subscriptions.
I would like to design a system using a proxy-server that maintains a single websocket connection to the data vendor and then relays the appropriate messages to the clients via websocket. Optimally, the clients would be able to interact with the proxy server as if it were the data vendor's API.
I have looked at various (reverse?) proxy server solutions here, but have not found specific language about reducing the number of connections to the upstream data source. For example, I have looked into NGINX, but I can't tell if the proxy will combine client connections into a single upstream connection. The other solution I have researched is just putting all messages into a Kafka Pub/Sub via a connector, and have each client subscribe there.
I am curious if there are any existing, out of the box solutions to this problem before I implement my own solution.

SignalR OnConnected firing on different server to the one which it's actually connected

I'm using SignalR and a web farm in IIS, currently with 3 servers and requests are load balanced via ARR.
There are certain external events that happen which I want to be processed by the server to which the client is connected. So I want to track which of the 3 servers the client is currently connected.
I thought that I could do this using OnConnected and within that method store the MachineName against the ConnectionID in redis.
The problem is that OnConnected seems to get called an a different server to the one that the client is connected to.
Upon investigating, it seems that there are three calls, one to /negiotate one to /connect and one to /start. The /connect seems to be the websocket connection that is kept up for the duration, the others are just transient.
These three connections can happen on different servers, and it seems that the websocket connection can be to server A (so that's the server that the client's SignalR connection is going to), but the OnConnected gets fired on server B.
I was wondering if I'm overlooking something that will let me see which server the SignalR connection is actually connected to?
Thanks,
Will
If you are going to use a web farm, then you need to implement a backplane to track all of the messaging.
https://learn.microsoft.com/en-us/aspnet/signalr/overview/performance/scaleout-in-signalr
Without a proper backplane implementation its impossible to do what you want to do.
I believe that is something you would have to save. Assuming you are using a database for mapping users, you could have an additional field such as "LoggedInOn" and store the server host name or other identifier.
However, other than some aspect of troubleshooting your are looking to do, proper send/receive of messages should cross the backplane to all servers. This way no matter which server they are connected to, messages are received.
If you have external events as you say, once they complete and a message is ready to be sent back to a client, the backplane should push that to all servers.
If that's not happening I would review the docs as Kelso Sharp stated.

SIGNALR Backplane - What happend when you send message to a group

When you configure SignalR to use a SQL Backplane and you send to a group, does SignalR create in the backplane one message for the group or one message for each client ID in the group.
I need two instances of my SignalR, but because clients have different connectionIds between instances, I need to send message to a unique identifier which could be the group.
Can anyone please answer this ?
Thanks
Each server instance connects to the backplane through the bus. When a message is sent, it goes to the backplane, and the backplane sends it to every server. When a server gets a message from the backplane, it puts the message in its local cache. The server then delivers messages to clients from its local cache.
As per: http://www.asp.net/signalr/overview/performance/scaleout-in-signalr
This means that the server (hub) would decide how to handle the message so you can do either.
This might help. http://www.asp.net/signalr/overview/performance/scaleout-with-sql-server

How to handle SignalR implementation under LoadBalancer Environment

I am fairly new to signalr concepts. I have a scenario where load balancing is in place with two servers. The situation is that client request is taken by the load balancer and redirects it to a one of the server based on the load. After redirection the connection from client to the server is lost. Important thing here is that client request is for different purposes i.e they call different methods on the hub. The server continues processing the request further and during this time if it detects any status change, it has to push the notification back to the clients. However at this point, server won't be knowing to which client it has to respond back as the load balancer doesn't store any information about the same once the connection is lost from client to server. How to handle this kind of scenario?. Should I be manually storing session id and other details in a table?
I have gone through the scaleout options suggested for load balancing using backplane by the signalr team(Azure service bus, Redis and SQL Server). However my scenario is little different. Any help will be appreciated.

Are all clients in a group assured to receive signalR calls when SignalR is scaled out behind load balancer?

I've been looking into SignalR implementation incorporated with a load balancer
and have a few basic (if not simple sounding) questions.
I must preface this by saying I've got zero (0) experience with load balancers.
We will have 2 servers sitting behind a load balancer.
The client is an ASP .Net application.
We've been told that the load balancer maintains session affinity.
Consider the following scenario:
Client1 & Client2 -- connect to GroupA--> Server1
Client3 & Client4 -- connect to GroupA--> Server2
1) Server1 makes a client call to GroupA - this assumes that
Clients 1-4 will get the notification, correct?
2) How does the processing occur on this?
3) Is it a function of SignalR itself, or the load balancer?
4) When sending messages at the group level, do messages only get delivered to the client
apps associated with the group on that specific server, or will messages get forwarded
to all clients of that group?
Does anyone have any thoughts on this?
Thanks,
JB
I believe the scenario you're looking at requires a SignalR Backplane to be setup.
Here's a relevant selection from the article but you'll want to read the full thing to answer your specific questions:
Each server instance connects to the backplane through the bus. When a
message is sent, it goes to the backplane, and the backplane sends it
to every server. When a server gets a message from the backplane, it
puts the message in its local cache. The server then delivers messages
to clients from its local cache.

Resources