5

NodeJs を使用してリアルタイム統計アプリケーションを構築しています。プロトタイプの場合、クラスター NodeJs ( http://learnboost.github.com/cluster/ ) とネイティブ nodejs ドライバーを使用する MongoDb を使用するnodejs サーバーでのテストのために、RackSpace サーバーでクアッドコア AMD Opteron を使用しています。.

基本的に、クライアントの Web サイトにコンテンツを配信する JS コードを会社のプロジェクトに挿入しました。このコードは、10 秒ごとにサーバーに "ping" を実行し、画像を呼び出し、サーバー側で取得して MongoDb コレクションに挿入 (または更新) するパラメーターを渡します。1日の「遅い」時間帯に、約3000の接続を取得します(ターミナルでnetstat -natpコマンドを使用してこれらを取得します)。これにより、クラスターが各コアの約25%を使用します(「top」コマンドを使用してこれらを取得します)。しかし、「忙しい」時間には、クラスターが狂うたびに約7000以上の接続が発生し(各コアの約80%以上の使用)、時間が経つにつれてノードが劣化するようです。これは正常ですか?それとも、Nodejs はこれらのヒットをより「簡単な」方法で処理する必要がありますか? Mongoose を使用すると、パフォーマンスが向上しますか?

MongoDb に興味がある場合は、1 つのコアの約 4% を使用しますが、これは私にとっては問題ありません (インデックスを配置しない場合、使用率は約 50% 以上でしたが、少なくとも、インデックスはこのパフォーマンスの問題を解決しました)。

辛抱強くありがとう、乾杯。

編集:

挿入を行うコードは次のようになります: db.open(function(err, db) { });

return connect.router(function(app){
    app.get("/pingserver/:clientid/:event/:cachecontrol", function(req, res, next){
    event:'+req.params.event + ', cachecontrol:' + req.params.cachecontrol);
        var timestamp = new Date(); 
          switch(req.params.event) {
          case 'load':
              var params = url.parse(req.url, true).query;

              db.collection('clientsessions', function(err, collection)         {
                try {

                    var client = {
                        id: req.params.clientid,
                        state: req.params.event + 'ed',
                        loadTime: timestamp.getTime(),
                        lastEvent: req.params.event,
                        lastEventTime: timestamp.getTime(),
                        lastEventDate: timestamp.toString(),
                        events: [{
                            event: req.params.event,
                            timestamp: timestamp.getTime(),
                            date: timestamp.toString()
                        }],
                        media: {
                            id: params.media.split('|')[0] || null,
                            title: unescape(params.media.split('|')[1]) || null
                        },
                        project: {
                            id: params.project.split('|')[0] || null,
                            name: unescape(params.project.split('|')[1]) || null
                        },
                        origin: req.headers['referer'] || req.headers['referrer'] || '',
                        userAgent: req.headers['user-agent'] || null,
                        userIp: req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)),
                        returningUser: false
                    };
                }catch(e) {console.log(e);}       
                 collection.insert(client, function(err, doc) {
                 });
              });
              break;

          case 'ping':
              db.collection('clientsessions', function(err, collection) {
                  collection.update({id: req.params.clientid}, { 
                                                     $set : { lastEvent: req.params.event 
                                                             ,lastEventTime: timestamp.getTime(),lastEventDate: timestamp.toString()}
                                                   }, {}, function(err, doc) {});
              });
              break;

          default:
              db.collection('clientsessions', function(err, collection) {
                  collection.update({id: req.params.clientid}, { 
                                                     $set : {state: req.params.event+'ed'
                                                            , lastEvent: req.params.event 
                                                            , lastEventTime: timestamp.getTime()}
                                                   , $push : { events : { event: req.params.event, timestamp: timestamp.getTime(), date: timestamp.toString() } } }, {}, function(err, doc) {});
              });

              break;
          }

          if (!transparent) {
              console.log('!transparent');
              transparent = fs.readFileSync(__dirname + '/../../public/images/transparent.gif', 'binary');
          }
          res.setHeader('Content-Type', 'image/gif');
          res.setHeader('Content-Length', transparent.length);

          res.end(transparent, 'binary');
      });
});
4

6 に答える 6

2

これは正常ですか?

依存しますが、接続は自然に消えますか? 彼らはただ構築を続けていますか?「Web接続」(http)またはMongoDB接続について話しているのですか?

ログには何と書かれていmongodますか? ログには何と書かれていnodeますか?

毎秒何件のリクエストを受け取っていますか?

それとも、Nodejs はこれらのヒットをより「簡単な」方法で処理する必要がありますか?

コードが何をしているかを知らずに言うのは難しいです。

ボックスが処理できる同時接続数はいくつですか?

Mongoose を使用すると、パフォーマンスが向上しますか?

node-mongodb-nativeしたがって、Mongoose は実際にはドライバーのオブジェクト ラッパーです。これは別のドライバーではなく、単なるラッパーです。

ラッパーは、既に持っているコードにコードを追加します。コードに問題がある場合、コードを追加しても問題が改善されるとは限りません。マングースが問題を解決する場合、それはあなたがしていない接続で何かをしている. その場合は、必ずしも Mongoose が必要というわけではなく、より優れた接続管理が必要なだけです。


問題の潜在的な原因がたくさんあることを確認してください。

これを解決する唯一の方法は、断片を分解し、より詳細に掘り下げることです。開始する場所: - MongoDB への接続は正しく終了していますか (db ログを参照)。- ログに他のエラーが含まれていますか? - ノード ログに対して同じことを行いますか? - メモリ使用量に関するグラフはありますか? 誰が最も多くのメモリを占有していますか? - 各コアの 80% に達したとき、これを行っているのはどのプロセスですか? mongod? node? 他の何か?

ここで本当にあなたを助けるために、システムで何が起こっているかについてもっと多くのデータが必要です.

于 2011-05-07T00:52:47.880 に答える
1

継続的なリクエストは、特にそれらの間のタイムアウトが小さい場合、非常にコストがかかる可能性があります。あなたの場合、1秒あたり最大300〜700以上の同時リクエストを受け入れており、システムの負荷は、何を処理しているかによって異なります。Mongooseに切り替えることもできますが、DBがボトルネックではないように思われるため(DBドライバーも問題になる可能性があります)、シナリオに適用できる場合は、イメージの処理とキャッシュを検討したいと思います。

于 2011-05-06T07:09:35.753 に答える
1
if (!transparent) {
          console.log('!transparent');
          transparent = fs.readFileSync(__dirname + '/../../public/images/transparent.gif', 'binary');
      }

透明な偽はどのくらいの頻度ですか? コードで定義されていません。潜在的にすべてのリクエストに対して、同期ディスク IO で Node プロセス全体をブロックしています。なんで?ディスクからファイルを読み取る必要がある場合は、非同期で行います。ファイルが静的で小さい場合は、一度メモリにロードする必要があります。

于 2011-05-10T20:00:13.093 に答える
0

ただの更新:

クラスターを削除し、サーバーにNginxレイヤーを配置しました。そのため、「劣化」するのにかなり長い時間がかかりましたが、それでもそれを実行しており、特にシステムのRAMメモリを大量に消費しています。何かご意見は?

そして、すべての答えに感謝します!

編集:いくつかのテストをやり直しました。主な問題はオープン接続に関するものだと思います。Nginxポートでnetstatを実行すると、2000接続のように表示されます。各nodejsアプリポートで実行すると、2000(またはそれ以上)と表示されます。基本的に、私の「最良のシナリオ」は、nodejsアプリで開いている接続の合計が、Nginxポートで開いている接続と一致するということです。これが主な問題であり、巨大な「time_wait」ステータスに影響を与えていると思います。

于 2011-05-12T12:52:56.933 に答える
0

ここで行われているように、バッファから透明な gif を提供したいだけかもしれません:

https://gist.github.com/657246#comments

于 2012-03-19T18:47:44.933 に答える