Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR and Browser Connection limit

Tags:

I made a simple app with SignalR for testing. When the page loads it calls a function on the server, that function then calls a client function that prints a message on the screen. I did that to check that both the client and server function works and SignalR communication works ok.

My problem is that if I open the same page on two different tabs (did it in Chrome), the first page loads ok, but the second page doesn't call the server's functions - ONLY if I close the first page.

So as far as I understand, their is probably a connection limitation that is related to the browser that doesn't allow SignalR to connect more then once (actually two, one for receiving and one for sending)

Update: I've find our that other tabs where open, but now I've checked it through and it allows only 4 tabs / pages to be active with connections. If I try to put the same page on a new tab no data is being sent, when I close one of the other tabs, the new tab sends the data right away.

What I wanted to know if there is any solution for that, because I want this connectivity to be available if the user decide to open the same page on two tabs or more.

I don't believe that it has anything to do with IIS, because from what I know it can accept thousands of connections.

like image 851
Idan Shechter Avatar asked Oct 04 '12 09:10

Idan Shechter


People also ask

How long does a SignalR connection last?

The default keepalive timeout period is currently 20 seconds. If your client code tries to call a Hub method while SignalR is in reconnecting mode, SignalR will try to send the command. Most of the time, such attempts will fail, but in some circumstances they might succeed.

What is the difference between SignalR and WebSockets?

WebSockets is actually the underlying transport that SignalR uses, at least most of the time. SignalR has the ability to fall back to other ways of transporting messages, such as long-polling over HTTP. This is useful in situations where you don't have WebSockets support.

Is SignalR scalable?

A SignalR app can scale out based on the number of messages sent, while the Azure SignalR Service scales to handle any number of connections.


2 Answers

This problem would be best addressed by the future Channel Messaging specification, which has not been implemented by any browsers to-date, but I managed to solve it by limiting the number of connections as described by Alex Ford and using localStorage as a message bus between tabs.

The storage event lets you propagate data between tabs while keeping a single SignalR connection open (thereby preventing connection saturation). Calling localStorage.setItem('sharedKey', sharedData) will raise the storage event in all other tabs (not the caller):

$(window).bind('storage', function (e) {
    var sharedData = localStorage.getItem('sharedKey');
    if (sharedData !== null)
        console.log(
            'A tab called localStorage.setItem("sharedData",'+sharedData+')'
        );
});

You can test if ($.connection.hub.state === 1) to determine if a given tab should notify the other tabs via localStorage (courtesy of Alex) to prevent duplicate localStorage.setItem calls.

Facebook overcomes this browser limitation by serving persistent connections over several sub-domains, but this can complicate deployment and testing.

Caveats

Old Connections: In Alex's solution, you need to be careful of Disconnect() not being called (e.g. exception), and you filling up your HubConnections bucket (or repository) with old hub connections. If the Session ID does not change (can happen), this may prevent new clients from establishing a SignalR connection even though none are active. Alternatively, timestamp new connections and have a sliding expiration to minimise potential impact.

Locking: localStorage may be subject to race conditions as it does not implement any locking as described here.

To support different types of events, you should encode an eventType in your JSON messages and test for it on the storage event.

Fallbacks

If a SignalR connection cannot be established, I fall back onto polling the server every 45 seconds to retrieve a notification count.

If you don't want to use localStorage, you can use cookies, but it's not as clean.

like image 166
Petrus Theron Avatar answered Nov 18 '22 21:11

Petrus Theron


I've created IWC-SignalR utility which allows to have single SignalR connection for all windows (tabs) of the same application.

How it works

One of the windows becomes a connection owner (choosen randomly) and holds the real SignalR connection. If connection owner is closed or crashed another window becomes a connection owner - this happens automatically. Inter-window communication is done by means of inter-window communication library (based on localStorage). This library provides functionality to communicate between windows as between parallel processes (locks, shared data, event bus...). Hope it will be useful for someone.

like image 39
Eugene Khudoy Avatar answered Nov 18 '22 20:11

Eugene Khudoy