SSE(EventSource): why no more than 6 connections?
Asked Answered
C

3

23

I wanted to see how many simultaneous SSE (aka EventSource) connections I could setup, before overloading my machine. But testing with Firefox (Firefox 18 or Firefox 20) it stopped at 6 connections: the additional connections give no error, but do not send any data. (In Firebug I can see them there, waiting to connect.) Chromium 25 also stopped at 6 connections, and so did Opera 12.15. But it does not seem to be a server-side limit (I'm using Apache + PHP), as I could run all three browsers at the same time (i.e. 18 connections), and all are coming from the same IP address. (Server and client are on the same machine, but using a 172.16.x.x address, not 127.0.0.1.)

So, I set the test up with CORS, and tried connecting to another server, which has a global IP. This time I get 12 connections for Firefox. Suggesting it is Apache configuration after all? No, Opera still only gets 6 connections. (No number for Chrome, as CORS does not appear to work.) I could also run connecting to both servers, for a total of 18 connections (but never any more) in Firefox, and a total of 12 in Opera.

As a 3rd test I moved both back-end and html to the remote server, and loaded the page that way. This time I hit a limit of 10 connections for Firefox!?! Opera still has a limit of 6. And Chromium (which works as there is no CORS involved this time) has a limit of 6.

I'd appreciate any insight into where this number 6 comes from, and if it is just coincidence that all three browsers are the same. And especially any insight into why Firefox is sometimes 6, sometimes 10, sometimes 12. (The SSE specification seems to leave the maximum number of connections undefined.)


Apache configuration is to use prefork, which means these settings:

StartServers          5
MinSpareServers       5
MaxSpareServers      10
MaxClients          150
MaxRequestsPerChild   0

(Both local (Ubuntu 10.04) and global (Ubuntu 11.10) servers have identical Apache settings here.) I believe the key number there is that MaxClients is 150. I did a quick experiment changing StartServers to 50, instead of 5, but got identical results.


Here is the client-side HTML/javascript (1 or 2 lines to uncomment, and modify, if you want to experiment connecting to a different server; as given here it expects to find sse.php in the same directory as the HTML):

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>SSE Stresstest</title>
</head>
<body>
<p id="err"></p>
<p id="x"></p>
<script>
function start(){

function onMessage(e){
document.getElementById('x').innerHTML+=e.origin+":"+this.dummy_n+":"+e.data+"<br/>";
};

function onError(e){
document.getElementById('err').innerHTML+="ERR:"+this.dummy_n+":"+JSON.stringify(e)+"<br/>";
};

for(var n=1;n<=32;++n){
    //NB. 't' primarily to avoid caching
    var url='sse.php?dummy_n='+n+'&t='+(new Date().getTime());
    //if(n%2==0)
    //    url='http://example.com/sse.php?dummy_n='+n+'&t='+(new Date().getTime());
    var es=new EventSource(url);
    es.dummy_n=n;   //So we can identify each one
    es.addEventListener('error',onError,false);
    es.addEventListener('message',onMessage,false);
    }
}

setTimeout("start()",1000);   //Only Safari needs the 1000ms delay.
</script>
</body>
</html>

And the backend sse.php script is like this:

<?php
$ip=array_key_exists('SERVER_ADDR',$_SERVER)?$_SERVER['SERVER_ADDR']:'cli';
header('Content-Type: text/event-stream');
header('Access-Control-Allow-Origin: *');   //CORS: allow access from anywhere
@ob_flush();@flush();
//Now the main loop
while(true){
    echo "data:".gmdate("Y-m-d H:i:s,").$ip."\n\n";
    @ob_flush();@flush();
    sleep(1);
    }
?>
Crt answered 31/5, 2013 at 8:10 Comment(0)
P
24

The reason could be every EventSource object initiates the new HTTP session and in fact opens new tcp/ip socket. Because of you're pushing data from server continuously in infinite loop, the socket keeps open continuously. All web browsers has an upper limit on simultaneous active HTTP/1 connections to the same server. Normally in range of 4 to 6 as per RFC 2616. Your browser just preventing new connection to be open as this limit to be exceeded.

With HTTP/2 and HTTP/3, the limit is higher (100 connections by default).

You may learn here some more info as well:
http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/

Pipit answered 31/5, 2013 at 8:40 Comment(4)
Excellent blog link, thanks. I was able to go to about:config in Firefox, find network.http.max-persistent-connections-per-server, change it from 6 to 16, and get 16 SSE connections!Crt
There actually is one more workaround possible with SSE. Surprisingly but even w/o endless loop it still works! The trick is EventSource object beign constructed once will continuously send GET request to server URL with some seconds-rate interval. Every some 4s in Chrome case and about 7s in FF case. In Firefox you may see this series of GETs in Firebug's Net tab. Then you may have much more SSE-activated web pages in browser all active as in fact there will be no long-lasting connections, just series of short-living request-response events.Pipit
@Pipit - well this kind of ruins SSE's purpose and added value. If we transform the long-lasting connections to short-living request-responces, we might as well go back to long polling.Deductive
@DarrenCook I guess you can't build a public facing application based on this technique, because all the users may not be able to follow your trick!Leaved
C
4

See the Connections per Hostname column here: http://www.browserscope.org/?category=network&v=1

More information than anyone could possibly want, and it shows the observed "6" is basically just convention.

RFC2616 suggests a limit of 2, but everyone ignores it. So http://trac.tools.ietf.org/wg/httpbis/trac/ticket/131 removes that suggestion.

Customization

It appears IE can be configured from the registry.

Firefox can be configured from within about:config, filter on network.http for various settings; network.http.max-persistent-connections-per-server is the one to change.

Chrome cannot be configured at the current time.

Opera can be configured by going to about:config, then opening "Performance" and changing "Max Persistent Connections Server".

Safari? No, not configurable, apparently.

Crt answered 31/5, 2013 at 11:5 Comment(0)
B
0

Referring this https://developer.mozilla.org/en-US/docs/Web/API/EventSource

It is stated that Firefox and Chrome set the limit on the number of connections opened by a browser + domain.

When not used over HTTP/2, SSE suffers from a limitation to the maximum number of open connections, which can be specially painful when opening various tabs as the limit is per browser and set to a very low number (6). The issue has been marked as "Won't fix" in Chrome and Firefox. This limit is per browser + domain, so that means that you can open 6 SSE connections across all of the tabs to www.example1.com and another 6 SSE connections to www.example2.com. (from Stackoverflow). When using HTTP/2, the maximum number of simultaneous HTTP streams is negotiated between the server and the client (defaults to 100).

Brace answered 17/6, 2020 at 11:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.