首页 > 解决方案 > NodeJS,Express:分叉的子进程无法使用池进行批量 MySQL 查询

问题描述

我的意图是在文件上传时,主 Node.JS 进程将分叉一个子进程,该子进程将解析上传的文件,然后进行批量(1K+)MySQL 查询。我希望孩子处理查询,因为我不希望父进程“阻塞”。由于父进程和子进程都需要访问我在包含 npm MySQL 池的外部文件中定义的 MySQL 连接:

mysqlConnector.js

// Load module
var mysql = require('mysql');
// Initialize pool
var pool      =    mysql.createPool({
    connectionLimit : 10,
    host     : 'localhost',
    port: 3306,
    user: 'bob',
    password: 'my_pass',
    database: 'my_db'
});    

const doQuery = (query_string) => {
  console.log(pool);
  pool.query(query_string, function (error, results, fields) {
    if (error) throw error;
    console.log('in doQuery: query' );
  });
};

exports.doQuery = doQuery;
exports.pool = pool

我可以将池和doQuery方法都导入我的主 Expressindex.js并毫无问题地使用它们:

index.js

const {doQuery, pool} = require('./mysqlConnector');

app.get('/', (req, res) => {

    const { username, password } = req.query;

    const GET_USER_QUERY = `select username, password from users where username = '${username}' and password = '${password}'`;
    doQuery(GET_USER_QUERY); //logically insignificant function call but wanted to verify doQuery works from here
    console.log(pool);
    pool.getConnection(function(err,connection){
        if (err) {
            connection.release();
            throw err;
        }   
        connection.query(GET_USER_QUERY, (err, results) => {
            if(!err) {
                console.log(results);
                connection.release();
                return res.json(results);
            }           
            else{
                console.log(err);
                connection.release();
            }
        });
    });
});

使用mysqlConnector.jsin一切正常index.js,但是,分叉的子进程可以成功导入并“看到”池对象,但当子进程尝试使用导出的池或函数mysqlConnector.js时,它“不起作用” 。doQuery

index.js这是将分叉一个孩子的代码块:

index.js

app.post('/upload', upload.single('thefile'), (req, res) => {
    const {username} = req.query;
    
    fileHandlerProcess = fork("./fileupload/handleprops.js");
    fileHandlerProcess.on('message', (msg) => {
        console.log(`PARENT: message from child process is ${msg}`);
        res.sendStatus(msg.status);
    });
    fileHandlerProcess.send({"filepath":`${__dirname}\\${req.file.path}`,"username":`${username}`});
});

这是handleprops.js,分叉的孩子将运行的js文件:

handleprops.js

const {execSync, fork} = require('child_process');
const {doQuery} = require('../mysqlConnector');

const exec_options = {
    cwd: null,
    env: null,
    encoding: 'utf8',
    timeout: 0,
    maxBuffer: 200 * 1024,
    killSignal: 'SIGTERM'
};


process.on('message', msg=>{

  if(msg.filepath && msg.username){
    execSync(`java -jar C:\\Users\\colli\\d2reader\\out\\artifacts\\d2reader_jar\\d2reader.jar ${msg.filepath}`, exec_options);

    var filename = msg.filepath.replace(/^.*[\\\/]/, '');
    filename = __dirname + "\\json\\" + filename.substring(0, filename.length-3) + "json";
    try{
      const fs = require('fs');
      const data = fs.readFileSync(filename, 'utf8');
      processSharedStashQueries(JSON.parse(data), msg.username);
    } catch(err) {
      console.error(err);
    }
    process.exit();
  }
});

const processSharedStashQueries = (data, username) => {
    const INSERT_USER_QUERY = `insert into sharedstashes  (NumStashes, SharedGold, NumItems, UserID) values (${data.numStashes}, ${data.sharedGold}, ${data.numItems}, (select id from users where username = '${username}'))`;
    doQuery(INSERT_USER_QUERY);

};

当孩子调用“doQuery()”时,池对象将被记录,我可以验证它是一个有效且已定义的对象,并且与父进程 (index.js) 使用的池对象完全相同。但是,当孩子点击“pool.query()”代码行时,什么也没有发生。没有错误,也没有控制台日志。就好像什么事都没发生一样。

为什么子进程可以“看到”池对象但不能使用它?

标签: javascriptmysqlnode.jsexpresschild-process

解决方案


推荐阅读