У меня есть приложение NodeJS, которое подключается к различным датчикам и запрашивает их текущее значение. Для этого у меня есть мастер-процесс, который контролирует текущие датчики с использованием MySQL и порождает дочерний процесс для каждого активного датчика. Дочерний процесс выполняется бесконечно. Он получает URL-адрес датчика каждые 15 секунд и записывает результат в базу данных Redis.
Поэтому обычно должен быть один главный процесс, а число дочерних процессов должно быть равно количеству датчиков. Однако я заметил, что в htop
я вижу, что для одного и того же датчика запущено несколько дочерних процессов. Еще более странным является то, что ps axf
сообщает только об одном дочернем процессе для каждого датчика.
Вот пример вывода ps axf
:
28079 ? Ss 0:00 \_ sshd: zolcsi [priv]
28157 ? S 0:00 | \_ sshd: zolcsi@pts/8
28158 pts/8 Ss 0:00 | \_ -bash
28173 pts/8 S 0:00 | \_ sudo su
28175 pts/8 S 0:00 | \_ su
28176 pts/8 S 0:00 | \_ bash
20424 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezes.js
20630 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 4 http://***.net/****
20631 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 5 http://***.net/****
20632 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 7 http://***.net/****
20633 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 9 http://***.net/****
20634 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 11 http://***.net/****
20635 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 12 http://***.net/****
20636 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 13 http://***.net/****
20637 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 14 http://***.net/****
20638 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 17 http://***.net/****
20639 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 18 http://***.net/****
20640 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 19 http://***.net/****
20641 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 20 http://***.net/****
20642 pts/8 Sl+ 0:00 | \_ node erzekeloLekerdezesChild.js 21 http://***.net/****
Число после имени файла является идентификатором датчика. А вот часть вывода из htop
:
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
20788 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
20791 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
20794 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
20797 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
21379 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
21717 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
21718 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
21719 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
21720 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.00 node erzekeloLekerdezesChild.js 4 http://***.net/****
20630 root 20 0 1160M 20048 5504 S 0.0 0.2 0:00.36 node erzekeloLekerdezesChild.js 4 http://***.net/****
Как видите, для датчика № 4 существует 10 процессов. Это довольно большая проблема, потому что имеется 250 датчиков, и эти процессы узлов в настоящий момент используют много памяти.
Итак, есть ли идеи о том, что представляют собой остальные 9 процессов (кроме PID 20630)?
Это соответствующий код основного процесса:
const { spawn } = require('child_process');
let children = {};
function erzekelokLekerdezes() {
let con = mysql.createConnection({
host: config.database.host,
user: config.database.user,
password: config.database.pass,
database: config.database.name
});
con.connect(function(err) {
con.query(
"SELECT " +
"FROM " +
"`LoxoneErzekelo` ",
function (err, result) {
for(let i = 0; i < result.length; i++) {
if(!result[i].Elo && children.hasOwnProperty(result[i].LoxoneErzekeloId)) {
//Sensor is off, but it has a running process, kill it
children[result[i].LoxoneErzekeloId].kill();
}
else if(result[i].Elo && !children.hasOwnProperty(result[i].LoxoneErzekeloId)) {
//Sensor is ON, and there is no child process for it, spawn one
let url = genUrl();
children[result[i].LoxoneErzekeloId] = spawn('node', [
'erzekeloLekerdezesChild.js',
result[i].LoxoneErzekeloId,
url,
result[i].Path
]);
children[result[i].LoxoneErzekeloId].on('exit', function () {
delete children[result[i].LoxoneErzekeloId];
});
}
}
//Re-check the sensors after one minute
setTimeout(erzekelokLekerdezes, 60000);
}
);
});
}
erzekelokLekerdezes();