2014-01-20 6 views
16

NodeJSとJavaのクイックパフォーマンステストを行っています。選択された単純なユースケースは、MySQLデータベース内の単一のテーブルを照会することです。NodeJSを複数のコアで線形にスケールする方法は?

Platform      | DB Connections | CPU Usage | Memory Usage | Requests/second 
==============================|================|===========|===============|================ 
Node 0.10/MySQL    | 20    | 34%  | 57M   | 1295 
JBoss EAP 6.2/JPA    | 20    | 100%  | 525M   | 4622 
Spring 3.2.6/JDBC/Tomcat 7.0 | 20    | 100%  | 860M   | 4275 

ノードのCPUとメモリの使用率はJavaよりも低いですが、スループットも約3分の1です。その後、JavaはCPU上で4つのコアすべてを利用していましたが、Nodeは1つのコアのみで実行されていました。そこで、ノード・コードを変更してクラスター・モジュールを組み込み、現在は4つのコアすべてを使用していました。 CPUとメモリの使用状況は、今比例上がっているが、スループットはわずか70%増になったことを

Platform      | DB Connections | CPU Usage | Memory Usage | Requests/second 
==============================|================|===========|===============|================ 
Node 0.10/MySQL (quad core) | 20 (5 x 4)  | 100%  | 228M (57 x 4) | 2213 

注:ここでは新しい結果があります。私はJavaのスループットを超えて4倍の増加が見込まれていました。どのように私は喪失を説明することができますか?スループットを直線的に上げるには何ができますか?ここで

は、複数のコアを利用するためのコードです:

if (Cluster.isMaster) { 
    var numCPUs = require("os").cpus().length; 
    for (var i = 0; i < numCPUs; i++) { 
     Cluster.fork(); 
    } 

    Cluster.on("exit", function(worker, code, signal) { 
     Cluster.fork(); 
    }); 
} 
else { 
    // Create an express app 
    var app = Express(); 
    app.use(Express.json()); 
    app.use(enableCORS); 
    app.use(Express.urlencoded()); 

    // Add routes 

    // GET /orders 
    app.get('/orders', OrderResource.findAll); 

    // Create an http server and give it the 
    // express app to handle http requests 
    var server = Http.createServer(app); 
    server.listen(8080, function() { 
     console.log('Listening on port 8080'); 
    }); 
} 

私は、データベースを照会するためのノード-mysqlのドライバを使用しています。接続プールはコアごとに5つの接続に設定されていますが、違いはありません。この番号を1または20に設定すると、ほぼ同じスループットになります。

var pool = Mysql.createPool({ 
    host: 'localhost', 
    user: 'bfoms_javaee', 
    password: 'bfoms_javaee', 
    database: 'bfoms_javaee', 
    connectionLimit: 5 
}); 

exports.findAll = function(req, res) { 
    pool.query('SELECT * FROM orders WHERE symbol="GOOG"', function(err, rows, fields) { 
     if (err) throw err; 
     res.send(rows); 
    }); 
}; 
+0

'NODE_ENV = production'試してみることもできますhttps://groups.google.com/forum/#!topic/express-js/fqtr1Carr0E – KeepCalmAndCarryOn

+0

また、接続を正しくプールしていますか?これは推奨される方法です。 'var mysql = require( 'mysql'); var pool = mysql.createPool(...); pool.getConnection(function(err、connection){ //接続を使用する 接続。{//接続で完了しました。 connection.release(); //ここでは接続を使用しないでください。プール。 }); }); 'https://github.com/felixge/node-mysql – KeepCalmAndCarryOn

+0

はい、正しくプールを使用しています。私が示しているコードは、あなたが持っているものの短いカットです(私はそれを両方の方法で試しました)。これをこのノード-mysqlの問題(https://github.com/felixge/node-mysql/issues/712)で広範に説明しました。 – Naresh

答えて

1

環境変数export NODE_CLUSTER_SCHED_POLICY="rr"を設定してみてください。 this blog postに従って。

+0

この記事では、NodeJSバージョン0.12について説明しています。これは、http://nodejs.org/でまだ利用できません。また、ラウンドロビンアルゴリズムはWindowsのパフォーマンスに影響を与えないと言います。これは私がテストを行っているところです。 – Naresh

+1

はい、それはv0.10の最新バージョンにも実際に適用されます。しかし、それは特にLinuxカーネルのスケジューラの一面を補っているので、Windowsでは必要ありません。 –

2

私が見るところでは、プラットフォームだけでなくフレームワークも比較していません。フレームワーク効果を取り除き、プレーンなHTTPサーバーを実装したいと思うかもしれません。たとえば、Expressアプリケーションのすべてのミドルウェアはレイテンシを加算します。また、Javaライブラリが頻繁に要求されるデータをキャッシュしないようにして、パフォーマンスが大幅に向上することを確認しましたか?

ノード内のhttpモジュール(つまり、node-mysqlを含むすべてのライブラリが組み込まれています)は、Agentクラスを介して内部接続プールを維持します(MySQL接続プールと混同しないように注意してください)、HTTPキープアライブを利用できるようにします。これは、TCP接続を開いたり、HTTP要求を出したり、応答を取得したり、TCP接続を閉じたり、繰り返したりするのではなく、同じサーバーに対して多くの要求を実行しているときに、パフォーマンスを向上させるのに役立ちます。したがって、TCP接続を再利用することができます。

デフォルトでは、HTTPエージェントは、MySQLサーバーなどの単一のホストへの5つの同時接続のみを開きます。これは簡単に次のように変更できます。

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

これらの変更を考慮して、どのような改善が得られるかを確認してください。

その他のアイデアは、MySQL接続プールが正しく接続されているかどうかを確認することです。頻繁に開かれる場合は、node-mysqlのアイドルタイムアウト値を増やす必要があります。

+0

アイデアありがとう。私は現在、他のものに焦点を当てていますが、これらの提案を試してもらうためにトドゥがあります。 – Naresh

関連する問題