2011-11-13 1 views
17

Итак, у меня есть проблема. Если возникает неперехваченное исключение, когда я обрабатываю HTTP-запрос, у меня нет возможности вызвать метод end() для объекта http.ServerResponse. Поэтому сервер зависает навсегда и никогда не выполняет запрос.Восстановление из неуправляемого исключения в Node.JS

Вот пример:

var express = require('express'); 
var app = express.createServer(); 
var reqNum = 0; 
app.get('/favicon.ico', function(req, res) {res.send(404);}); 
app.get('*', function(req, res, next) { 
    console.log("Request #", ++reqNum, ":", req.url); 
    next(); 
}); 
app.get('/error', function(req, res, next) { 
    throw new Error("Problem occurred"); 
}); 
app.get('/hang', function(req, res, next) { 
    console.log("In /hang route"); 
    setTimeout(function() { 
     console.log("In /hang callback"); 
     if(reqNum >= 3) 
      throw new Error("Problem occurred"); 
     res.send("It worked!"); 
    }, 2000); 
}); 
process.on('uncaughtException', function(err) { 
    console.log("Uncaught exception!", err); 
}); 
app.listen(8080); 

Если вы посещаете/ошибка, происходит исключение, но ловится. Пользователь получает сообщение об ошибке - никаких проблем. Если я посещу/повесить, сервер, в конце концов, выкинет исключенное исключение и зависнет вечно. Любые последующие запросы/зависание будут зависать.

Это отстой. Любые советы по устранению этой проблемы?

ответ

16

Когда происходит неперехваченное исключение, вы находитесь в нечистом состоянии. Пусть процесс умирает и перезапускает его, нет ничего другого, что можно сделать, чтобы безопасно вернуть его в хорошо известное состояние. Используйте forever, он перезапустит ваш процесс, как только он умрет.

+6

Я согласен в определенной степени. В производственных средах вы не можете полностью отключить весь сервер только из-за одного неперехваченного исключения. Что делать, если на одной странице PHP возникла проблема? Спустился бы весь ваш веб-сервер? Я собирался отправить мне письмо по электронной почте, если произойдет неперехваченное исключение и автоматически отключится, если в течение 60 секунд произойдет более 10 событий. Но, действительно ... Я не хочу, чтобы сервер спустился и перезагрузился. Я хотел бы попытаться восстановиться. – BMiner

+0

@BMiner: вы можете использовать hook.io или так, чтобы разделить приложение на несколько процессов и встроенные кластерные материалы для создания отдельных рабочих процессов. Таким образом, не все идет вниз, просто часть необходимо перезапустить. – thejh

+3

@BMiner Перезапуск приложения проще, чем извинения клиента за повреждение данных. Как сказал адх, среда исполнения находится в нечистом состоянии. С этого момента вы должны предположить, что все является неопределенным поведением. –

1

Используйте try/catch/finally.

app.get('/hang', function(req, res, next) { 
    console.log("In /hang route"); 
    setTimeout(function() { 
     console.log("In /hang callback"); 
     try { 
      if(reqNum >= 3) 
       throw new Error("Problem occurred"); 
     } catch (err) { 
      console.log("There was an error", err); 
     } finally { 
      res.send("It worked!"); 
     } 
    }, 2000); 
}); 
+0

уродливые, но функциональные – Janka