マシンに過負荷をかける前に、セットアップできる同時 SSE (別名 EventSource) 接続の数を確認したかったのです。しかし、Firefox (Firefox 18 または Firefox 20) でテストしたところ、6 つの接続で停止しました。追加の接続ではエラーは発生しませんが、データは送信されません。(Firebug では、接続を待っている状態で表示されます。) Chromium 25 も 6 接続で停止し、Opera 12.15 も同様でした。しかし、サーバー側の制限ではないようです (私は Apache + PHP を使用しています)。3 つのブラウザーすべてを同時に実行でき (つまり、18 接続)、すべてが同じ IP アドレスから来ているためです。(サーバーとクライアントは同じマシン上にありますが、127.0.0.1 ではなく 172.16.xx アドレスを使用しています。)
そこで、CORS でテストをセットアップし、グローバル IP を持つ別のサーバーに接続してみました。今回は Firefox で 12 個の接続を取得しました。結局、それはApacheの構成であると示唆していますか? いいえ、Opera はまだ 6 つの接続しか取得できません。(CORS が機能していないように見えるため、Chrome の番号はありません。) また、両方のサーバーに接続して、Firefox で合計 18 の接続 (ただし、それ以上の接続はありません)、Opera で合計 12 の接続を実行することもできました。
3 番目のテストとして、バックエンドと html の両方をリモート サーバーに移動し、そのようにページをロードしました。今回は Firefox の接続数が 10 の制限に達しました!?! Opera にはまだ 6 の制限があります。また、Chromium (今回は CORS が関与していないため動作します) には 6 の制限があります。
この 6 という数字がどこから来たのか、また 3 つのブラウザがすべて同じであるというのが単なる偶然であるとしたら、何か洞察をいただければ幸いです。特に、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 を 5 ではなく 50 に変更して簡単な実験を行いましたが、結果は同じでした。結果。
クライアント側の 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);
}
?>