0

私はいくつかの負荷テストを行っており、それを行うためのノード スクリプトを作成しています。私のテスト コードが原因であることに気付くまで、私の結果はかなり貧弱でした。私は、平均して 1 秒あたり約 30 ~ 50 件のリクエスト (サーバーへの) を行っており、以下のコードを使用してリクエストを作成しています。30-50 は非常に低いようです。これは 4 コアの Mac 上にあります。これは正しいですか、それとも私は何か完全に間違っていますか?

var http = require('http');
var sys = require('util');

http.globalAgent.maxSockets = 100000;

var http = require('http');
http.globalAgent.maxSockets = 100000;

var Request = function (request, params, host, port, completionFn, errorFn)
{
  if(!params)
    params = '';

  if(typeof(errorFn) != 'function')
  {
    errorFn = function (e)
        {
          console.log('request error!? ' + e.message);
          process.exit();
        }
  }

  var paramsStr = '';
  for(var item in params)
    paramsStr += '&' + item + '=' + encodeURI(params[item]);

  var path = '/' + request;
  if(paramsStr != '')
    path += '?' + paramsStr.substr(1);

  var options =
  {
    host:     host,
    port:     port,
    path:     path,
    agent:    false
  };

  http.request(options,

    function (response)
    {
      var responseData = '';

      response.on('data',

        function (chunk)
        {
          responseData += chunk;
        }

      ).on('end',

        function ()
        {
          completionFn(httpRequest.To_JSON(responseData));
        }

      ).on('error', errorFn);
    }

  ).on('error', errorFn).end();
};

新しい情報:

興味深いことに、これを Chrome で実行すると、1 秒あたり約 250 のリクエストが得られます。これは、単一のノードではより合理的と思われます。ブラウザはすぐにクラッシュしますが。

for(var i = 0; i < 1000000; i++)
{
  $.get('/service', {index:i},function(result){}).error(

    function()
    {
      out.append('fail ');
    }
  );
}
4

1 に答える 1

0
/*jshint node:true */
var http = require('http');

var i = 100;

var called = 0;

while (i--) {
    requestGoogle();
}

function requestGoogle() {
    'use strict';
    var requestNum = called++;

    console.log('CALLED: ' + called);
    var options = {
        hostname: 'www.google.com',
        port: 80,
        path: '/',
        method: 'GET'
    };

    var req = http.request(options, function (res) {
        res.setEncoding('utf8');
        res.on('data', function () {
            console.log('RECIEVING DATA ON: ' + requestNum);
        });

        res.on('end', function () {
            console.log('CALLED: ' + --called);
        });
    });

    req.on('error', function (e) {
        console.log('problem with request: ' + e.message);
    });

    req.end();
}

この例を実行すると、2 つのことがわかります。1 つ目は、最初は、さまざまな要求に対して適切なデータが混在していることです。

データ受信中: 2 データ受信中: 0 データ受信中: 2 データ受信中: 0 データ受信中: 3 データ受信中: 3 データ受信中: 3 データ受信中: 3 データ受信中: 3 データ受信中: 3データ受信中: 3 データ受信中: 1 データ受信中: 1 データ受信中: 1 データ受信中: 1 データ受信中: 1 データ受信中: 1 データ受信中: 1 データ受信中: 1 データ受信中: 4データ受信中: 4 データ受信中: 4

リクエスト 1、4、3、0、2 からのチャンクが表示されています... すべてが同時に入ってきます... すごいですね! しばらくすると、この動作は結果の非常に直線的なセットになり、ミキシングはまったく発生しません。最終的に、キューに入れられたリクエストでイベント ループを混雑させます。このロジック サーバー サイドを実行する場合、この即時ループ関数呼び出しではなく、文字通り瞬時に要求をキューに入れます。サーバーに送信されるリクエストの数に関係なく (DDOS 条件を除く)、ノード プロセスがそのイベント ハンドラーを呼び出してメイン イベント ループに戻るまでの貴重なサイクルはほとんどありません。

クライアント、while ループ、スポーン リクエストを実行すると、これらの貴重な数サイクルが利用できなくなります。代わりに、混雑したイベント ループがあり、その結果、リクエストが基本的に直線的に処理されます。最初の 10 ~ 13 のリクエストがデータを受信すると、順番に受信が開始され、予想よりもはるかに遅くなります。 、混雑したイベントループがあるため、ノードがサーバー側の要求を処理できる速度と比較して. あなたのクライアント プログラムは本質的に自分自身を DOS しました! :)。

ソケットの数を増やすことでこの動作を抑えることができますが、最終的にはマシンのファイル記述子が不足します。この時点で、ノードは関連する呼び出しでエラー ハンドラーをクラッシュ/呼び出しするか、速度を落としてファイル記述子が使用可能になるまで待機し、将来の要求を非常に直線的で同期的な方法で処理します。ファイル記述子を増やす方法はありますが、最終的には、適切にベンチマークするには複数のマシンが必要です。オペレーティング システムは、単一のノード サーバーであっても十分なストレス テストを実行できるだけの十分な数のソケット記述子/ネットワーク I/O を処理するようには設計されていません。この場合、DDOS 攻撃ははるかに簡単になります。

また、JMeter を調べてください。ストレス テストのクライアント側では、ノードよりもはるかに優れています。

于 2013-06-26T07:33:56.527 に答える