SSE(EventSource):为什么不超过 6 个连接? [英] SSE(EventSource): why no more than 6 connections?

查看:42
本文介绍了SSE(EventSource):为什么不超过 6 个连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的机器超载之前,我想看看我可以设置多少个同步 SSE(又名 EventSource)连接.但是使用 Firefox(Firefox 18 或 Firefox 20)进行测试时,它在 6 个连接处停止:附加连接没有错误,但不发送任何数据.(在 Firebug 中,我可以在那里看到它们,等待连接.)Chromium 25 也停止在 6 个连接处,Opera 12.15 也是如此.但这似乎不是服务器端限制(我使用的是 Apache + PHP),因为我可以同时运行所有三个浏览器(即 18 个连接),并且都来自同一个 IP 地址.(服务器和客户端在同一台机器上,但使用的是 172.16.x.x 地址,而不是 127.0.0.1.)

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.)

因此,我使用 CORS 设置了测试,并尝试连接到另一台具有全局 IP 的服务器.这次我获得了 12 个 Firefox 连接.暗示它毕竟是Apache配置?不,Opera 仍然只能获得 6 个连接.(Chrome 没有数字,因为 CORS 似乎不起作用.)我还可以连接到两台服务器,在 Firefox 中总共有 18 个连接(但不会再有),在 Opera 中总共有 12 个连接.

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.

作为第三个测试,我将后端和 html 都移到了远程服务器,并以这种方式加载了页面.这次我达到了 Firefox 10 个连接的限制!?!Opera 仍然有 6 的限制.而 Chromium(由于这次没有涉及 CORS 可以工作)有 6 的限制.

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.

如果您能深入了解这个数字 6 的来源,以及所有三个浏览器都相同是否只是巧合,我将不胜感激.尤其是关于为什么 Firefox 有时是 6,有时是 10,有时是 12 的任何见解.(SSE 规范 似乎未定义最大连接数.)

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配置是使用prefork,意思是这些设置:

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

StartServers          5
MinSpareServers       5
MaxSpareServers      10
MaxClients          150
MaxRequestsPerChild   0

(本地 (Ubuntu 10.04) 和全局 (Ubuntu 11.10) 服务器在此处具有相同的 Apache 设置.)我相信关键数字是 MaxClients 是 150.我做了一个快速实验,将 StartServers 改为 50,而不是 5,但得到了相同的结果.

(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.

这是客户端的 HTML/javascript(如果您想尝试连接到不同的服务器,则需要 1 或 2 行取消注释和修改;正如此处给出的,它希望在与HTML):

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>

而后端sse.php脚本是这样的:

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);
    }
?>

推荐答案

原因可能是每个 EventSource 对象都启动了新的 HTTP 会话,实际上打开了新的 tcp/ip 套接字.由于您在无限循环中不断地从服务器推送数据,因此套接字始终保持打开状态.所有 Web 浏览器对 同时 到同一服务器的活动 HTTP/1 连接都有上限.根据 RFC 2616,通常在 4 到 6 的范围内.您的浏览器只是阻止打开新连接,因为超出此限制.

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.

对于 HTTP/2 和 HTTP/3,限制更高(默认为 100 个连接).

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

您也可以在这里了解更多信息:
http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/

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

这篇关于SSE(EventSource):为什么不超过 6 个连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆