我想看看在我的机器超载之前我可以同时设置多少个 SSE(又名 EventSource)连接。但是用 Firefox(Firefox 18 或 Firefox 20)测试它在 6 个连接处停止:额外的连接没有错误,但不发送任何数据。(在 Firebug 中,我可以看到它们在那里等待连接。) Chromium 25 也停止在 6 个连接处,Opera 12.15 也是如此。但这似乎不是服务器端的限制(我使用的是 Apache + PHP),因为我可以同时运行所有三个浏览器(即 18 个连接),并且都来自同一个 IP 地址。(服务器和客户端在同一台机器上,但使用 172.16.xx 地址,而不是 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 的任何见解。(SSE 规范似乎未定义最大连接数。)
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);
}
?>