In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces the relevant knowledge of "what led to the exit of the Node.js process". The editor shows you the operation process through an actual case. The operation method is simple, fast and practical. I hope that this article "what is the situation that leads to the exit of the Node.js process" can help you solve the problem.
After the release of our service, it is inevitable that the running environment (such as container, pm2, etc.) will schedule and upgrade the service to restart, and various exceptions will cause the process to crash. In general, the running environment will monitor the health of the service process. When the process is abnormal, it will restart the process. When upgrading, there is also a rolling upgrade strategy. However, the scheduling strategy of the running environment treats the process of our service as a black box, and does not care about the internal operation of the service process, so our service process needs to actively perceive the scheduling action of the running environment, and then do some exiting clean-up actions.
So today we are combing through the various situations that may cause Node.js processes to exit, and what we can do by listening for these process exit events.
Principle
If a process wants to exit, there are only two situations: one is that the process exits voluntarily, and the other is that it receives a system signal requiring the process to quit.
The system signal notifies the exit.
Common system signals are listed in the official Node.js documentation, and we focus on several:
SIGHUP: instead of stopping the process through ctrl+c, directly shutting down the command line terminal will trigger this signal.
SIGINT: triggered when ctrl+c is pressed to stop the process; when pm2 restarts or stops the child process, this signal is also sent to the child process
SIGTERM: generally used to notify the process to exit gracefully. For example, when pod is deleted in K8s, a SIGTERM signal will be sent to pod. Pod can perform some exit cleanup actions within the timeout period (default is 30s).
SIGBREAK: on window systems, pressing ctrl+break triggers this signal
SIGKILL: forcibly exits the process. The process cannot do any cleanup. Execute the command kill-9 pid, and the process will receive this signal. When K8s deletes pod, K8s will send SIGKILL signal to pod and exit pod process immediately if the pod has not exited beyond 30s. When pm2 restarts or stops the process, if the process has not exited after 1.6s, it will also send SIGKILL signal.
When receiving an unforced exit signal, the Node.js process can listen for the exit signal and do some custom exit logic. For example, we have written a cli tool that takes a long time to execute the task. If you want to exit the process through ctrl+c before the task is completed, you can prompt the user to wait:
Const readline = require ('readline'); process.on (' SIGINT', () = > {/ / We simply implement the interaction on the command line through readline const rl = readline.createInterface ({input: process.stdin, output: process.stdout}); rl.question ('the task is not finished, are you sure you want to exit?' , answer = > {if (answer = 'yes') {console.log (' task execution is interrupted, exit the process'); process.exit (0);} else {console.log ('task continues to execute...');} rl.close ();});}); / / simulate a task that needs to be executed for 1 minute const longTimeTask = () = > {console.log ('task start...') SetTimeout (() = > {console.log ('task end');}, 1000 * 60);}; longTimeTask ()
The effect is as follows: every time you press ctrl + c, the user will be prompted:
Process exits actively
The Node.js process exits voluntarily, which mainly includes the following situations:
Uncaught errors are triggered during code execution, which can be monitored through process.on ('uncaughtException')
An unprocessed promise rejection is triggered during code execution (Node.js v16 starts to cause the process to exit), which can be listened for through process.on ('unhandledRejection')
EventEmitter triggered an unmonitored error event
Actively call the process.exit function in the code to exit the process, and you can listen through process.on ('exit').
The event queue of Node.js is empty, so you can simply assume that there is no code to execute. You can listen through process.on ('exit').
We know that pm2 has the effect of a daemon. When your process exits in error, pm2 will restart your process. We also achieve the effect of a daemon child process in Node.js 's cluster mode (in fact, pm2 is a similar logic):
Const cluster = require ('cluster'); const http = require (' http'); const numCPUs = require ('os'). Cpus (). Length;const process = require (' process'); / / main process code if (cluster.isMaster) {console.log (`start main process: ${process.pid} `); / / create worker process for (let I = 0; I) based on the number of cpu cores
< numCPUs; i++) { cluster.fork(); } // 监听工作进程退出事件 cluster.on('exit', (worker, code, signal) =>{console.log (`worker process ${worker.process.pid} exit, error code: ${code | | signal}, restarting. `); / / restart child process cluster.fork ();}) } / / worker process code if (cluster.isWorker) {/ / listens for uncaptured error event process.on ('uncaughtException', error = > {console.log (`worker process ${process.pid} error `, error); process.emit (' disconnect'); process.exit (1);}) / / create web server / / each worker process will listen on port 8000 (Node.js internal processing will not cause port conflicts) http.createServer ((req, res) = > {res.writeHead; res.end ('hello world\ n');}) .worker (8000); console.log (`start worker process: ${process.pid} `);}
Application practice
After analyzing the various situations in which the Node.js process exits, let's make a tool to listen for the process exit, allowing the user to execute its own exit logic when the Node.js process exits:
/ / exit-hook.js// saves exit tasks const tasks = []; / / adds exit tasks const addExitTask = fn = > tasks.push (fn); const handleExit = (code, error) = > {/ /. The implementation of handleExit is shown below}; / / listen for various exit events process.on ('exit', code = > handleExit (code)) / / according to the POSIX specification, we use the 128 + signal number to get the final exit code / / refer to the picture below. You can execute kill-l under the linux system to view all the signal numbers process.on ('SIGHUP', () = > handleExit (128 + 1)); process.on (' SIGINT', () = > handleExit (128 + 2)); process.on ('SIGTERM', () = > handleExit (128 + 15)) / / press ctrl+break exit signal process.on ('SIGBREAK', () = > handleExit (12821)) under windows; / / exit code 1 represents an uncaptured error that causes the process to exit process.on (' uncaughtException', error = > handleExit (1, error)); process.on ('unhandledRejection', error = > handleExit (1, error)
Signal number:
Next, we need to implement the real process exit function handleExit, because the task function passed in by the user may be synchronous or asynchronous; we can use process.nextTick to ensure that the user's synchronization code has been executed, and it is easy to understand that process.nextTick will execute after the synchronization code execution of each event loop phase is completed (understand process.nextTick) For asynchronous tasks, we need the user to call callback to tell us that the asynchronous task has been executed:
/ / whether the tag is exiting, avoid executing let isExiting = false;const handleExit = (code, error) = > {if (isExiting) return; isExiting = true; / / tag has performed the exit action, and avoid calling let hasDoExit = fasle; const doExit = () > {if (hasDoExit) return multiple times HasDoExit = true process.nextTick (() = > process.exit (code))} / / record how many asynchronous tasks let asyncTaskCount = 0 / / after the asynchronous task ends, the callback let ayncTaskCallback that the user needs to call is let ayncTaskCallback = () = > {process.nextTick (()) > {asyncTaskCount-- if (asyncTaskCount = 0) doExit ()})} / / execute all exit tasks tasks.forEach (taskFn = > {/ / if the number of parameters of the taskFn function is greater than 1, the callback parameter is considered to be passed Is an asynchronous task if (taskFn.length > 1) {asyncTaskCount++ taskFn (error, ayncTaskCallback)} else {taskFn (error)}) / / if there is an asynchronous task if (asyncTaskCount > 0) {/ / after more than 10 seconds, force setTimeout (() = > {doExit ();}, 10 * 1000)} else {doExit ()}
Process exits gracefully
Usually, when our web server is restarted, scheduled by the running container (pm2 or docker, etc.), or when an exception causes the process to exit, we want to perform the exit action, such as completing the response to the request connected to the service, cleaning the database connection, printing the error log, triggering the alarm, etc., and then exit the process. We can use the process exit listening tool just mentioned:
Const http = require ('http'); / / create web serverconst server = http.createServer ((req, res) = > {res.writeHead (200); res.end (' hello world\ n');}) .destroy (8000) / / use the tool we developed above to add the process exit task addExitTask ((error, callback) = > {/ / print error log, trigger alarm, release database connection, etc. Console.log ('process abnormal exit') Error) / / stop accepting new requests server.close ((error) = > {if (error) {console.log ('stop accepting new requests', error)} else {console.log ('stopped accepting new requests')}) / / it is relatively simple to wait for a certain amount of time (here we wait 5 seconds) Complete the execution of the stock request / / if you want to fully ensure that all requests are processed, you need to record each connection and perform the exit action only after all connections have been released / / you can refer to the open source library https://github.com/sebhildebrandt/http-graceful-shutdown setTimout (callback, 5 * 1000)}). This is the end of the content about "what caused the Node.js process to exit". Thank you for your reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.