我想看看在我的机器超载之前我可以设置多少个并发 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。)
因此,我使用 CORS 设置测试,并尝试连接到另一台具有全局 IP 的服务器。这次我得到了 12 个 Firefox 连接。到底是 Apache 配置吗?不,Opera 仍然只有 6 个连接。 (Chrome 没有这个数字,因为 CORS 似乎不起作用。)我还可以运行到两台服务器的连接,在 Firefox 中总共有 18 个连接(但不再有更多),在 Opera 中总共有 12 个连接。
作为第三个测试,我将后端和 html 都移动到远程服务器,并以这种方式加载页面。这次我达到了 Firefox 10 个连接的限制!?! Opera 的限制仍然是 6。而 Chromium(由于这次不涉及 CORS,所以可以工作)的限制是 6。
如果您能了解这个数字 6 的来源,以及所有三个浏览器都是相同的是否只是巧合,我将不胜感激。尤其是对为什么 Firefox 有时是 6、有时是 10、有时是 12 的深入了解。(上交所规范 http://dev.w3.org/html5/eventsource/似乎未定义最大连接数。)
Apache配置是使用prefork,这意味着这些设置:
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
(本地 (Ubuntu 10.04) 和全局 (Ubuntu 11.10) 服务器在此处具有相同的 Apache 设置。)
我相信关键数字是 MaxClients 是 150。我做了一个快速实验,将 StartServers 更改为 50,而不是 5,但得到了相同的结果。
这是客户端 HTML/javascript(如果您想尝试连接到不同的服务器,则需要取消注释和修改 1 或 2 行;如此处给出的,它期望在与 HTML 相同的目录中找到 sse.php):
<!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脚本是这样的:
<?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);
}
?>