node.jsの新機能モジュールから子プロセスでコードを実行しようとしています。
説明させてください、私はindex.jsに私の単純なサーバーを持っています
var server = http.createServer(handleRequest);
server.listen(PORT, function(){
console.log("Server listening on: http://localhost:%s", PORT);
});
URLがフェッチされると、子プロセスを起動します。
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で、firebaseの管理者、認証情報、データベースを初期化します。
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にインポート/実行する必要があることです。私はユーザーrequireを試みます...しかしnothinは機能しています。私の質問もより一般的です。別のファイルにいくつかのヘルパー(作成、読み取り、削除)を書き込みたいのですが、同じ問題が発生します。助けてくれてありがとう。
ライブJavascriptオブジェクトを別のプロセスに渡すことはできません。オブジェクトにJavascriptデータのみが含まれている場合は、JSONでシリアル化し、コピーが逆シリアル化される他のプロセスに渡すことができますが、ネイティブコードまたはTCP接続が背後にあるオブジェクトでは機能しない可能性があります開いているデータベースハンドルが表すもの。TCP接続を別のプロセスに渡すことができる状況がいくつかあります(クラスタリングはそれを行います)が、別の接続オブジェクト(通常はそうです)でラップしている場合は、ライブ接続オブジェクトを再構成するのは大変な作業です別のプロセスで渡されたTCP接続。個人的には、面倒なことは避けたいと思います。
子プロセスで重いCPU作業が行われている場合を除いて、ここで子プロセスが必要になる理由はまったくありません。リクエストが届いたときに、メインプロセスでやりたいデータベース作業を行うことができます。データベース作業はほとんど非同期である必要があるため、メインのnode.jsスレッドをそれほどブロックしないようにし、複数のリクエストを実行できるようにする必要があります。同時に。リクエストが多いと、とにかくデータベースがボトルネックになり、メインのnode.jsプロセスではありません。
子プロセスを使用する正当な理由があり、各プロセスの新しいDB接続を開いたり閉じたりしたくない場合は、開いたままにしておく一連のワーカープロセスを作成することをお勧めします。次に、データベースへの独自の接続を開き、開いたままにしておくことができます。新しいリクエストがメインのnode.jsプロセスに到着したら、何らかの形式のIPC(おそらく子プロセスのstdinに書き込むだけ)を使用して、処理を待機している新しいジョブを送信します。スループットを最適化するために必要な作業プロセスの数を決定することで、物事を最適化できます。次に、新しいジョブが入ってくると、そのジョブをキューにドロップするだけです。無料のワーカーがいる場合は、キュー内の次のジョブをそのワーカーに送信します。労働者が仕事を終えるたびに、あなたはそこにあるかどうかを確認します
このようにすることで、データベースへの新しい接続を常に作成および強制終了するわけではなく、各ワーカープロセスは独自のデータベース接続を保持できます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加