Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR through Load Balancer

Tags:

signalr

I am having a strange issue with SignalR through different load balancers (I have tried elastic load balancer and HAProxy).

My setup is as follows:

C# client -> HAProxy --> (SignalR Host 1 or SignalR Host 2)

The HAProxy is configured to roundrobin with cookies to ensure session stickiness

balance roundrobin
cookie SERVERID insert indirect nocache

When I have a single SignalR host behind the proxy (using Long Polling or Server Send Event) everything works fine. I can connect, invoke methods and handle callbacks.

As soon as I add a 2nd SignalR server things start to go poorly. I can connect fine and the connections properly load balance. I can send messages and they properly stick to the server. The problem is that callbacks just never make it back to my client through the proxy.

What is perplexing is this works fine with a single host configured on the load balancer.

Another note: I am not looking to scale out SignalR with a backplane. My signalr hosts don't need to know about each other or care about clients connected. In my architecture SignalR is the frontend to an application layer tier that handles communication service wide. I am essentially using Signlar to support push notifications from the application.

Thoughts?

like image 388
bsmatt Avatar asked Oct 25 '25 14:10

bsmatt


1 Answers

I figured this out...

It turns out the problem was I wasn't handling the sticky session properly. Specifically, I wasn't associating the backend server cookie that the load balancer creates with my hub connection. The result is that the keep-alive was coming from one host where the other host was getting all the messages from the client so my client was effectively timing out silently. I enabled all the System.Diagnostics from signalr to figure this out.

I never figured out how to handle the stickiness during the connection process (probably creating a new persistentconnection class and handling connection messages). Instead I did it as part of a login process that is using REST calls. I retrieve the cookie from those calls and add that to the cookie container of the hubconnection and the sessions properly stick.

Update: Here is how you set the cookie in the hub connection

std::unordered_map<utility::string_t, utility::string_t> ConnectionHeaders;
ConnectionHeaders[U("Cookie")] = <INSERT COOKIE>
m_HubConnection->set_headers(ConnectionHeaders);

Thanks

like image 191
bsmatt Avatar answered Oct 28 '25 05:10

bsmatt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!