2017-11-27 20 views
1

new to node.jsモジュールから子プロセスでいくつかのコードを実行しようとしています。子プロセスからnode.jsでコードを実行

URLは私が子プロセスを起動フェッチされると、私はindex.js

var server = http.createServer(handleRequest); 

server.listen(PORT, function(){ 
    console.log("Server listening on: http://localhost:%s", PORT); 
}); 

に私の単純なサーバーを持って、私に説明してみましょう:

function handleRequest(req, res){ 
    console.log('Request path = ' + req.url) 
    launchWorker(req.url) 
    res.end('Path Hit: ' + req.url); 
} 

// workers execution 
function launchWorker(path) { 
    const worker = child_process.spawn('node', ['./worker.js', path.substring(1)]) 

    worker.stdout.on('data', function(data) { 
     console.log('worker: ' + data.toString()) 
    }); 

    worker.stderr.on('data', function(data) { 
     console.log('stderr : ' + data) 
    }); 

    worker.on('close', function(code, signal) { 
     console.log('child process exited with code: ' + code) 
    }); 
} 

だから私はworker.jsファイルを持っていますいくつかのコードを実行すると、サーバから私の子プロセスにいくつかのデータを渡しました['./worker.js', path.substring(1)]

私はfirebaseを使っていくつかの操作を実行していますので、私のworker.jsで私はf irebase管理者、資格情報&データベース:

var admin = require("firebase-admin"); 

var serviceAccount = require("./service_account.json"); 

var defaultApp = admin.initializeApp({ 
    credential: admin.credential.cert(serviceAccount), 
    databaseURL: "http://myAdress.firebase" 
}); 

var db = admin.database() 

performWork() 

function performWork() { 

    var arg = process.argv[2] 
    var ref = db.ref("something"); 
    ref.once("value", function(snapshot) { 
     console.log(arg); 
     process.exit(1); 
    }); 

} 

私は毎分プロセスを起動するつもりですので、私は私がやりたいことは、私の子供に引数としてfirebaseデータベースを与えることですので、私は作成しないでください私がプロセスを起動するたびにfirebaseにアクセスできます。 だから、これは私がindex.jsで行うことを試みたものです:

var admin = require("firebase-admin"); 

var serviceAccount = require("./service_account.json"); 

var defaultApp = admin.initializeApp({ 
    credential: admin.credential.cert(serviceAccount), 
    databaseURL: "http://myAdress.firebase" 
}); 

var db = admin.database() 

...

function launchWorker(path) { 
    const worker = child_process.spawn('node', ['./worker.js', path.substring(1), admin.database()]) 

私は単に私の労働者への引数としてデータベースを渡します。 はその後、私の労働者に私がFB取得:

function performWork() { 

    var arg = process.argv[2] 
    var db = process.argv[3] 
    var ref = db.ref("something"); 
    ref.once("value", function(snapshot) { 
     console.log(arg); 
     process.exit(1); 
    }); 

} 

をしかし、私は、URLに達したとき、私はエラーを取得する:

TypeError: db.ref is not a function 
    at performWork (/home/user/worker.js:12:15) 
    at Object.<anonymous> (/home/user/worker.js:6:1) 
    at Module._compile (module.js:635:30) 
    at Object.Module._extensions..js (module.js:646:10) 
    at Module.load (module.js:554:32) 
    at tryModuleLoad (module.js:497:12) 
    at Function.Module._load (module.js:489:3) 
    at Function.Module.runMain (module.js:676:10) 
    at startup (bootstrap_node.js:187:16) 
    at bootstrap_node.js:608:3 

私はworker.jsがfirebase全く知らないと思う、とすることはできません関数.refに到達します。 dbがnullでなくても(私はその値を出力することができます) firebaseモジュールからコードを実行できるように、worker.jsでインポート/実行する必要があるのは私の質問ですか?私はユーザーに要求します...しかし、何も働いていません。 私の質問もより一般的です。私はいくつかのヘルパー(作成、読み取り、削除)を別のファイルに書きたいと思いますが、同じ問題が発生します。 ありがとうございました。

+0

なぜ子プロセスを使用する必要があると思いますか?私は彼らが必要であると示唆するものは何も見ていないし、子プロセスを使用することは無視できないパフォーマンスのペナルティが付属しています。 – josh3736

+0

私は、メモリを解放するために子プロセスを使用する必要があります。それは頻繁に呼び出される重いタスクです。これは、プロセスが完了したときに本当にメモリを解放するために見つけた唯一の方法です。 – FloAtri

答えて

1

ライブのJavascriptオブジェクトを別のプロセスに渡すことはできません。オブジェクトにJavascriptデータのみが含まれている場合は、JSONを使用してシリアル化し、コピーを逆シリアル化する他のプロセスに渡すことはできますが、その背後にネイティブコードまたはTCP接続があるオブジェクトでは機能しません開いているデータベースハンドルが表すものTCP接続を別のプロセスに渡すことができるいくつかの状況がありますが(クラスタリングではそうしていますが)、別の接続オブジェクトにラップされている場合(通常は)、ライブ接続オブジェクトを再構成する作業別のプロセスで渡されたTCP接続。個人的に、私はむしろそのすべての面倒を避けるだろう。

あなたの子プロセスで重いCPUの作業が行われていない限り、ここでは子プロセスが必要な理由はありません。要求が到着したときに、メインプロセスで必要なデータベース作業を行うことができます。データベース作業は主に非同期でなければならず、メインnode.jsスレッドをかなりブロックするべきではなく、飛行中に複数の要求を持つことができます。同じ時間。多くの要求があると、データベースはボトルネックになります。メインのnode.jsプロセスではありません。

子プロセスを使用する正当な理由があり、それぞれに新しいDB接続を開いて閉じたくない場合は、開かれたままのワーカープロセスを作成したいと思うかもしれません。その後、データベースへの独自の接続を開いて開いたままにすることができます。あなたのメインのnode.jsプロセスに新しいリクエストが到着したときには、何らかの形のIPC(子プロセスのstdinへの書き込み)を使用して、新しいジョブを送信します。スループットを最適化する必要がある作業プロセスの数を決定して、最適化することができます。次に、新しいジョブが入ったら、ジョブをキューにドロップします。フリーのワーカーがいる場合は、キュー内の次のジョブをそのワーカーに送信します。ワーカーがジョブを終了するたびに、キュー内にそのワーカーを送信する別のアイテムがあるかどうかをチェックします。

このようにすると、データベースへの新しい接続を常に作成して終了させることはなく、各ワーカープロセスは独自のデータベース接続を保持し、保持することができます。

+0

説明してくれてありがとうございます。はい、私は膨大な数のデータを扱うために(30秒に1回、毎分に1回、5回に1回、10回に1回...)、多くのデータを扱いますgb ram、それは私がメモリを解放するために見つけた唯一の方法です。子プロセスが終了し、すべてがリリースされます。私のサーバは、メモリ不足のためにリブートせずに月にこのプロセスを実行できます。ありがとう。 – FloAtri

+0

よろしくお願いします。 – FloAtri

関連する問題