Node js получить и установить данные из разных процессов
У меня есть приложение node, которое выполнило запуск (дочерний процесс) и приложение,
приложение имеет хост и порт:
var exec = require('child_process').spawn;
var child = exec('start app');
console.log("Child Proc ID " + child.pid)
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
console.log('stdout: ' + data);
});
child.on('close', function(code) {
console.log('closing code: ' + code);
});
некоторое приложение начнется немедленно, и некоторое приложение займет некоторое время 10-20 секунд, пока не начнет.
Теперь я использую прокси-сервер node http для запуска приложения, и проблема в том, что Im получает сообщение об ошибке, когда приложение хочет запустить приложение до его запуска и запуска.
Любая идея как-то я могу решить эту проблему?
proxy.on('error', function (err, req, res) {
res.end('Cannot run app');
});
Btw, я не могу отправить ответ 500 в прокси-ошибке из-за ограничения нашей структуры. Любая другая идея, как я могу отслеживать приложение, возможно, с некоторым таймаутом, чтобы увидеть, как он отправляет ответ 200.
UPDATE - пример моей логики
httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});
http.createServer(function (req, res) {
console.log("App proxy new port is: " + 5000)
res.end("Request received on " + 5000);
}).listen(5000);
function proxyRequest(req, res) {
var hostname = req.headers.host.split(":")[0];
proxy.web(req, res, {
target: 'http://' + hostname + ':' + 5000
});
proxy.on('error', function (err, req, res) {
res.end('Cannot run app');
});
}
Ответы
Ответ 1
Вам нужно послушать первый ответ на свой прокси-сервер и посмотреть его код состояния, чтобы определить, было ли ваше приложение успешно запущено или нет. Вот как вы это делаете:
proxy.on('proxyRes', function (proxyRes, req, res) {
// Your target app is definitely up and running now because it just sent a response;
// Use the status code now to determine whether the app started successfully or not
var status = res.statusCode;
});
Надеюсь, что это поможет.
Ответ 2
Не уверен, что это имеет смысл. В вашем основном приложении опыт должен начинаться с html-страницы, и каждый дочерний процесс должен иметь собственный загрузчик.
Итак, в основном вам нужен обработчик http, который задерживает запрос до тех пор, пока дочерний процесс не будет готов. Так что просто сделайте ajax-вызов из html и покажите анимацию загрузки, пока служба не будет готова.
//Ajax call for each process and update the UI accordingly
$.get('/services/status/100').then(function(resp) {
$('#service-100').html(resp.responseText);
})
//server side code (express syntax)
app.get('/services/status/:id ', function(req,res) {
// Check if service is ready
serviceManager.isReady(req.params.id, function(err, serviceStats) {
if(err) {
//do logic err here , maybe notify the ui if an error occurred
res.send(err);
return;
}
// notify the ui , that the service is ready to run , and hide loader
res.send(serviceStats);
});
})
Ответ 3
Я не уверен, что правильно понимаю вопрос, но вы хотите дождаться, когда дочерний процесс начнет вращаться по запросу, и вы хотите, чтобы этот запрос дождался этого дочернего процесса и затем был отправлен на него?
Если это так простое решение, мы будем использовать что-то вроде этого
var count = 0;//Counter to check
var maxDelay = 45;//In Seconds
var checkEverySeconds = 1;//In seconds
async.whilst(
function () {
return count < maxDelay;
},
function (callback) {
count++;
self.getAppStatus(apiKey, function (err, status) {
if (status != 200) {
return setTimeout(callback, checkEverySeconds * 1000);
}
continueWithRequest();
});
},
function (err) {
if (err) {
return continueWithRequest(new Error('process cannot spin!'));
}
}
);
Функция continueWithRequest() переадресует запрос дочернему процессу, и getAppStatus вернет 200, когда начался дочерний процесс, и какой-то другой код, когда он не является. Общая идея заключается в том, что каждый раз проверяется каждый раз, если процесс выполняется, и через 45 секунд, если нет, он вернет ошибку. Время ожидания и интервалы проверки можно легко отрегулировать. Это немного грубо, но будет работать для задержки запроса, а setTimeout запустит новый стек и не будет блокироваться. Надеюсь, это поможет.
Ответ 4
Если вы знаете (вокруг), сколько времени требуется для запуска приложения, просто добавьте setTimeout(proxyRequest, <Time it takes the app to start in MS>)
(Есть, скорее всего, более умные/сложные решения, но этот самый простой.)
Ответ 5
Почему бы не использовать событие-эмиттер или мессенджер?
var eventEmitter = require('event-emitter')
var childStart = require('./someChildProcess').start()
if (childStart !== true) {
eventEmitter.emit('progNotRun', {
data: data
})
}
function proxyRequest(req, res) {
var hostname = req.headers.host.split(":")[0];
proxy.web(req, res, {
target: 'http://' + hostname + ':' + 5000
});
eventEmitter.on('progNotRun', function(data) {
res.end('Cannot run app', data);
})
}