4

ソケット接続を介してnode.jsでsqlite3データベースをクエリすると、次の2つの問題が発生します。

  1. node.jshttpクライアントでnode.jshttpサーバーをリクエストすると、結果のシーケンスが混同されます

  2. 時々ソケットがハングアップしますが、再現できません

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

var http = require('http');
var url = require('url');
var sqlite3 = require('sqlite3').verbose();
var counter = 0;


//create sqlite database for testing
var db = new sqlite3.Database("db.sqlite3");
db.serialize(function() {
  db.run("DROP TABLE IF EXISTS test");
  db.run("CREATE TABLE IF NOT EXISTS test (ID INTEGER)");

  var stmt = db.prepare("INSERT INTO test VALUES (?)");
  for (var i = 1; i <= 10; i++) {
      stmt.run(i);
  }
  stmt.finalize();
});
db.close();



//run server
http.createServer(function (req, res) {

    var queryData = url.parse(req.url, true).query;
    res.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"});//, "connection": "keep-alive"


    var db = new sqlite3.Database(new Buffer(queryData.SQLServerAddress, "base64").toString('utf8'));
    db.serialize(function() {
        db.each(new Buffer(queryData.SQLStatement, "base64").toString('utf8'), function(err, row) {
            counter++;
            console.log(counter + " / " + JSON.stringify(row));
            res.end(JSON.stringify(row).toString());
        });
    });
    db.close();
    counter = 0;
}).listen(1337, '127.0.0.1');

console.log('Server running...');

そして、これがクライアントコードです:

var http = require('http');

for(i=1;i<=10;i++){
    var SQLServerAddress = new Buffer("db.sqlite3").toString('base64');
    var SQLStatement = new Buffer("SELECT * FROM test WHERE ID=" + i).toString('base64');


    var options = {
        host: "127.0.0.1",
        port: 1337,
        path: "/?SQLServerAddress=" + SQLServerAddress + "&SQLStatement=" + SQLStatement
    };


    callback = function(response){
        var str = "";
        response.on("data", function (chunk){
            str += chunk;
        });

        response.on("end", function (){
            console.log(str);
        });
    }
    http.request(options, callback).end();
}

私は「ストレステスト」としてリクエストを10回繰り返します。

だから私がコンソールで受け取るのは例えば

サーバー側コンソール:

1 / {"ID":1}
2 / {"ID":2}
3 / {"ID":5}
4 / {"ID":4}
1 / {"ID":3}
2 / {"ID":6}
1 / {"ID":7}
2 / {"ID":9}
3 / {"ID":10}
4 / undefined

そしてクライアント側のコンソール:

{"ID":1}
{"ID":2}
{"ID":5}
{"ID":4}
{"ID":3}
{"ID":6}
{"ID":7}
{"ID":9}
{"ID":10}

events.js:68
        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: socket hang up
    at createHangUpError (http.js:1263:15)
    at Socket.socketCloseListener (http.js:1314:23)
    at Socket.EventEmitter.emit (events.js:123:20)
    at Socket._destroy.destroyed (net.js:357:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)

私の質問は次のとおりです。

  1. 結果を正しい順序に保つにはどうすればよいですか?
  2. ソケットがハングアップしないようにするにはどうすればよいですか?

前もって感謝します!

4

1 に答える 1

1

Node.jsは、非同期イベントベースの環境です。

したがって、関数を呼び出すforループを実行すると、これらの関数が処理キューに追加されるだけで、関数が終了するのを待つことはありません。

したがって、すべてのリクエストは並行して開始され、どちらが最初に終了/送信されるかは保証されません。順序を保証する場合は、要求を同期的に送信する必要があります。以下のコードはテストされていませんが、1つのリクエストが終了すると、次のリクエストが開始されます(これはforループに配置されません)。

var count = 0;
callback = function(response){
    var str = "";
    response.on("data", function (chunk){
        str += chunk;
    });

    response.on("end", function (){
        if (count++ < 10){
          http.request(options, callback).end();
        }
        console.log(str);
    });
}
http.request(options, callback).end();

残念ながら、ソケットハングアップエラーから回復するための最良の方法はわかりませんが、http.requestメソッドをtry / catchで囲み、前のリクエストでエラーが発生した場合は、単に新しいリクエストを開始することができます。

于 2012-12-15T07:01:52.750 に答える