node.js가 충돌하는 것을 어떻게 방지합니까? try-catch가 작동하지 않습니다
내 경험상 PHP 서버는 로그 또는 서버 쪽에서 예외를 throw하지만 node.js는 단순히 충돌합니다. 모든 코드가 비동기 적으로 수행되므로 try-catch로 코드를 둘러 쌀 수 없습니다. 프로덕션 서버에서 다른 사람들이 무엇을하는지 알고 싶습니다.
http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception 에서 Node의 자체 문서를 읽을 수 있으므로 다른 답변은 정말 미쳤습니다.
누군가 다른 명시된 답변을 사용하는 경우 노드 문서를 읽으십시오.
참고
uncaughtException
예외 처리를위한 매우 조질기구이며 향후 제거 될 수있다
PM2
우선, 나는 높게 설치하는 것이 좋습니다 PM2
위해 Node.js
. PM2는 충돌을 처리하고 노드 앱을 모니터링하고로드 밸런싱에 정말 좋습니다. PM2는 충돌이 발생하거나 어떤 이유로 든 서버가 다시 시작될 때마다 Node 앱을 즉시 시작합니다. 따라서 언젠가 코드를 관리 한 후에도 앱이 중단되면 PM2가 즉시 다시 시작할 수 있습니다. 자세한 내용은 PM2 설치 및 실행
이제 앱 자체의 충돌을 막기위한 솔루션으로 돌아 왔습니다.
그래서 나는 마침내 Node 문서 자체가 제안하는 것을 생각해 냈습니다.
사용하지 마십시오
uncaughtException
, 사용domains
으로cluster
대신. 를 사용하는 경우uncaughtException
처리되지 않은 모든 예외 후에 응용 프로그램을 다시 시작하십시오!
DOMAIN 와 클러스터
우리가 실제로하는 일은 오류를 유발 한 요청에 대해 오류 응답을 보내면서 다른 사람들이 정상적인 시간에 끝내도록하고 해당 작업자의 새 요청을 듣지 않는 것입니다.
이런 식으로, 마스터 프로세스가 작업자에게 오류가 발생하면 마스터 프로세스가 새 작업자를 분기 할 수 있으므로 도메인 사용은 클러스터 모듈과 함께 사용됩니다. 내가 의미하는 바를 이해하려면 아래 코드를 참조하십시오
을 사용하고을 사용하여 Domain
프로그램을 여러 작업자 프로세스로 분리하는 복원력을 통해 Cluster
보다 적절하게 대응하고 훨씬 더 안전하게 오류를 처리 할 수 있습니다.
var cluster = require('cluster');
var PORT = +process.env.PORT || 1337;
if(cluster.isMaster)
{
cluster.fork();
cluster.fork();
cluster.on('disconnect', function(worker)
{
console.error('disconnect!');
cluster.fork();
});
}
else
{
var domain = require('domain');
var server = require('http').createServer(function(req, res)
{
var d = domain.create();
d.on('error', function(er)
{
//something unexpected occurred
console.error('error', er.stack);
try
{
//make sure we close down within 30 seconds
var killtimer = setTimeout(function()
{
process.exit(1);
}, 30000);
// But don't keep the process open just for that!
killtimer.unref();
//stop taking new requests.
server.close();
//Let the master know we're dead. This will trigger a
//'disconnect' in the cluster master, and then it will fork
//a new worker.
cluster.worker.disconnect();
//send an error to the request that triggered the problem
res.statusCode = 500;
res.setHeader('content-type', 'text/plain');
res.end('Oops, there was a problem!\n');
}
catch (er2)
{
//oh well, not much we can do at this point.
console.error('Error sending 500!', er2.stack);
}
});
//Because req and res were created before this domain existed,
//we need to explicitly add them.
d.add(req);
d.add(res);
//Now run the handler function in the domain.
d.run(function()
{
//You'd put your fancy application logic here.
handleRequest(req, res);
});
});
server.listen(PORT);
}
비록 Domain
중단 보류하고 새로운 교체로 노드의 문서에 명시되어 제공으로 제거됩니다
This module is pending deprecation. Once a replacement API has been finalized, this module will be fully deprecated. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future.
But until the new replacement is not introduced, Domain with Cluster is the only good solution what Node Documentation suggests.
For in-depth understanding Domain
and Cluster
read
https://nodejs.org/api/domain.html#domain_domain (Stability: 0 - Deprecated
)
https://nodejs.org/api/cluster.html
Thanks to @Stanley Luo for sharing us this wonderful in-depth explanation on Cluster and Domains
I put this code right under my require statements and global declarations:
process.on('uncaughtException', function (err) {
console.error(err);
console.log("Node NOT Exiting...");
});
works for me. the only thing i don't like about it is I don't get as much info as I would if I just let the thing crash.
As mentioned here you'll find error.stack
provides a more complete error message such as the line number that caused the error:
process.on('uncaughtException', function (error) {
console.log(error.stack);
});
Try supervisor
npm install supervisor
supervisor app.js
Or you can install forever
instead.
All this will do is recover your server when it crashes by restarting it.
forever
can be used within the code to gracefully recover any processes that crash.
The forever
docs have solid information on exit/error handling programmatically.
Using try-catch may solve the uncaught errors, but in some complex situations, it won't do the job right such as catching async function. Remember that in Node, any async function calls can contain a potential app crashing operation.
Using uncaughtException
is a workaround but it is recognized as inefficient and is likely to be removed in the future versions of Node, so don't count on it.
Ideal solution is to use domain: http://nodejs.org/api/domain.html
To make sure your app is up and running even your server crashed, use the following steps:
use node cluster to fork multiple process per core. So if one process died, another process will be auto boot up. Check out: http://nodejs.org/api/cluster.html
use domain to catch async operation instead of using try-catch or uncaught. I'm not saying that try-catch or uncaught is bad thought!
use forever/supervisor to monitor your services
add daemon to run your node app: http://upstart.ubuntu.com
hope this helps!
Give a try to pm2 node module it is far consistent and has great documentation. Production process manager for Node.js apps with a built-in load balancer. please avoid uncaughtException for this problem. https://github.com/Unitech/pm2
UncaughtException is "a very crude mechanism" (so true) and domains are deprecated now. However, we still need some mechanism to catch errors around (logical) domains. The library:
https://github.com/vacuumlabs/yacol
can help you do this. With a little of extra writing you can have nice domain semantics all around your code!
Works great on restify:
server.on('uncaughtException', function (req, res, route, err) {
log.info('******* Begin Error *******\n%s\n*******\n%s\n******* End Error *******', route, err.stack);
if (!res.headersSent) {
return res.send(500, {ok: false});
}
res.write('\n');
res.end();
});
'Programming' 카테고리의 다른 글
UISearchDisplayController / UISearchBar를 사용하여 NSFetchedResultsController (CoreData)를 필터링하는 방법 (0) | 2020.06.16 |
---|---|
Ansible이 홈 디렉토리에 .retry 파일을 작성하지 못하게하려면 어떻게합니까? (0) | 2020.06.16 |
정수 목록을 보유 할 SQL 변수 (0) | 2020.06.16 |
여러 ID 값을 허용하는 T-SQL 저장 프로 시저 (0) | 2020.06.16 |
Windows 용 Git Credential Manager를 비활성화하려면 어떻게합니까? (0) | 2020.06.16 |