1

サーバーから一連の tcp クライアントにキープアライブを送信しようとしています。応答に対するサーバーの負荷を軽減するために、キープアライブを分散させたいと考えています。

3000 の tcp クライアントがあり、60 秒のキープアライブ間隔がある場合、キープアライブ メッセージを 60 秒以上ずらして、毎秒 50 個のキープ アライブを送信する必要があります。

仮定:

  1. 多くの TCP 接続 (数千単位)
  2. TCP 接続は持続し、少なくとも数時間はアクティブであると予想されます
  3. サーバーは、クライアントが接続されなくなった場合、たとえば 60 秒以内に知る必要があります
  4. サーバーとクライアントからのその他の情報が送受信されます
  5. クライアントからのキープアライブリターンメッセージには有用なデータが含まれています(UDPを除外すると思います)

現在、私の考えは、特定の接続自体へのIDマッピングを使用して、標準のjavascriptオブジェクトとしてtcp接続を保存することです。次に、毎秒、このオブジェクトのキーの配列を取得し、これらの一部にキープアライブを送信します。

これは良いアプローチですか?私が考慮すべきより良いアプローチやその他のことはありますか?

問題に対する私の最初の刺し傷のコード例:

var KEEP_ALIVE_INTERVAL = 1000; // time between groups
var KEEP_ALIVE_CYCLE = 3; // number of groups
var tcp_conns = {
    a:"a",
    b:"b",
    c:"c",
    d:"d",
    e:"e",
    f:"f",
    g:"g",
    h:"h",
    i:"i"
};

var intervalCounter = 0;
setInterval(function() {

    console.log("sending keep alives intervalCounter="+intervalCounter);

    var numConns = Object.keys(tcp_conns).length;
    var connFactor = Math.ceil( numConns / KEEP_ALIVE_CYCLE );
    var lowerLimit = connFactor*intervalCounter-1;
    var upperLimit = connFactor*(intervalCounter+1);

    console.log("connFactor="+connFactor+", limits=["+lowerLimit+","+upperLimit+"]");

    // Is this even async???
    var keys = Object.keys(tcp_conns)
    for (var i = 0; i < keys.length; i++) {
        if(i>lowerLimit && i<upperLimit){
            var key = keys[i]
            var val = tcp_conns[key]
            console.log(" id="+key+" => "+val);
        }
    }

    intervalCounter++;
    if(intervalCounter==KEEP_ALIVE_CYCLE){
        intervalCounter=0;
    }
}, KEEP_ALIVE_INTERVAL);
4

1 に答える 1

1

すべての接続を含むコレクションを明示的に管理するのではなく、キープアライブを 45 秒から 75 秒ごとにランダムに送信します。このようにして、キープアライブは時間の経過とともに分散されます。次のコードがそのまま機能するかどうかはわかりませんが、基本的な考え方は理解できるでしょう。

  • 「PONG」は単一のチャンクとして到着すると想定していますが、そうではない可能性があります。
  • リスナーが漏れないように注意してください。ここでは、PING を送信するときに「データ」ハンドラーを追加し、PONG を取得するときにそれを削除します。最も効率的なソリューションではありません。

コードは次のとおりです。

var KEEP_ALIVE_TIMEOUT = 120*1000,
    MIN_KEEP_ALIVE = 45*1000,
    MAX_KEEP_ALIVE = 75*1000;

function randomInt(min, max) {
    return Math.random()*(max - min) + min;
}

net.createServer(function(conn) {
  function ping() {
     var keepAliveTimer = setTimeout(function() {
       conn.destroy();
       console.log('timeout !');
     }, KEEP_ALIVE_TIMEOUT);

     conn.write('PING\r\n');

     conn.on('data', function onData(chunk) {
        if(chunk.toString() !== 'PONG\r\n')
          return handleSomethingElse();

        clearTimeout(keepAliveTimer);
        conn.removeListener('data', onData);
        setTimeout(ping, randomInt(MIN_KEEP_ALIVE, MAX_KEEP_ALIVE));
     });
  }

  ping();
});
于 2012-08-09T17:33:17.010 に答える