JVM exits safely (how to gracefully shut down the Java service)

Source: Internet
Author: User

Background

User: The goods are arrived, shopping cart how to have just bought things, what?
Products: There are users reflect, bill of lading completed, how not clear shopping cart, research and development to see if there is a bug ah?
Research and development: Well, let me see! @#¥%......&* () A wild look, search GA, then on the line, restart the application, the asynchronous task lost ...
Product: Can line, on-line you lose the task, throw not ashamed Ah!
R & d:............

Go online! restart! Are you still worried about losing your mission? Look here to see here, never lose the task, the JVM can safely exit

In the transaction process, in order to improve the performance of the service, we have done some asynchronous optimization, such as updating the user's most recently used address, the bill of lading after the completion of the MQ to send a variety of notification class messages, clean up the user's shopping cart and so on these operations, asynchronous speed up the application of the response and also a hidden danger, How can I guarantee the execution of asynchronous operations? This scenario occurs primarily when an application is restarted, and the asynchronous operation performed in the background may not be completed when the JVM restarts through a thread or thread pool. At this point, the JVM can be shut down after the JVM is safely shut down to ensure that the asynchronous operation is completed.
More broadly, many applications on Linux are often forced to kill processes by Kill-9 PID, which is simple and efficient, so many application stop scripts often choose the way to use kill-9 pid. Forcing a process to exit can have some side effects that are equivalent to a sudden power-down for the application and may cause some of the following problems:

    1. The data in the cache has not been persisted to the disk, resulting in data loss;
    2. The write operation of the file is in progress, no update completed, suddenly exited, resulting in file corruption;
    3. The task queue in the thread pool has received tasks that have not yet been processed, causing the task to be lost;
    4. The database operation has been completed, such as the account balance update, ready to return the reply message to the client, the message is still queued in the communication thread to wait for the send queue, the process of forced exit caused the reply message is not returned to the client, the client initiated a timeout retry, will bring a duplicate update problem;
    5. Other problems, etc...

These problems are likely to have an impact on our business, causing unnecessary losses, to avoid these problems, we need to do some cleanup when the JVM shuts down, so the JVM provides a closure hook (shutdown hooks) to do these things. This article discusses the use of closed hooks related content.

JVM shutdown

First, we understand what will cause the JVM to shut down, such as

In the case of forced shutdown, the system shuts down, the operating system notifies the JVM that the process is shut down and waits, and once the wait times out, the system forces the JVM process to abort, kill-9, Runtime.halt (), power outages, system crash These methods will not be discussed directly to abort the JVM process, The JVM does not have the opportunity to perform the cleanup at all. Therefore, for applications, we strongly do not recommend the use of kill-9 this violent way out.
In the case of normal shutdown and abnormal shutdown, a registered shutdown hooks is called before the JVM shuts down, and based on this mechanism, we can put the work done in shutdown hooks, which will allow our application to safely exit. Based on the commonality of the platform, we recommend that applications use System.exit (0) to exit the JVM in this way.

The JVM interacts with the shutdown hooks, as shown, to learn more about the shutdown hooks working principle.

JVM Security Exits

For the Tomcat class Web application, we can register the custom hooks directly through the Runtime.addshutdownhook Thread Hook, implement the resource cleanup in the hooks, and for the worker class application, we can safely exit the application in the following way.

Signal-based process notification mechanism

The signal is a simulation of the interrupt mechanism at the software level, in principle, a process receives a signal that the processor receives an interrupt request can be said to be the same. In layman's terms, a signal is an asynchronous communication mechanism between processes. The signal has platform affinity, and some of the termination process signals supported by the Linux platform are as follows:

Signal name Use
SIGKILL Terminate process, Force kill process
SIGTERM termination process, software termination signal
Sigtstp Stop the process, the terminal comes to the stop signal
Sigprof Terminate process, statistical distribution graph with timer to time
SIGUSR1 Terminate process, user-defined signal 1
SIGUSR2 Terminate process, user-defined signal 2
SIGINT Terminating a process, interrupting a process
Sigquit Build the core file to terminate the process and generate the core file

There are some differences in the Windows platform, and some of its signals are shown in the following examples:

Signal name Use
SIGINT CTRL + C Interrupt
SIGTERM Termination of the software sent by kill
Sigbreak Ctrl+break Interrupt

Signal selection: In order to not interfere with the normal signal operation, but also to simulate the Java asynchronous notification, on Linux we need to select a special signal. By looking at the description on the signal list, we found that SIGUSR1 and SIGUSR2 are the signals that allow the user to customize, we can choose SIGUSR2, we can choose SIGINT on Windows.

With this signaling mechanism, a specific signal is sent to the application JVM, and the JVM can perceive and process the signal, which in turn can accept the program exit instruction.

Secure Exit implementation

First, look at the flowchart of the generic JVM security exit:

The first step is to initialize the signal instance when the application process starts, and its code example is as follows:

1 New Signal (Getossignaltype ());

Where the argument to the signal constructor is a string string, also the semaphore name described above.

The second step, according to the operating system name to obtain the corresponding signal name, the code is as follows:

1 Private String Getossignaltype () 2    {3        return system.getproperties (). GetProperty ("Os.name"). 4                  toLowerCase (). StartsWith ("Win")? "INT": "USR2"; 5     }

Determine whether the Windows operating system, if so select SIGINT, receive the command CTRL + C interrupt, otherwise select the USR2 signal, receive SIGUSR2 (equivalent to kill-12 pid) instructions.

The third step is to register the instantiated Signalhandler with the JVM's signal, and once the JVM process receives kill-12 or CTRL + C, the callback handle interface, the code example is as follows:

1 Signal.handle (SIG, Shutdownhandler);

Where Shutdownhandler implements the handle (Signal Sgin) method of the Signalhandler interface, the code example is as follows:

1  Public classShutdownhandlerImplementsSignalhandler {2     /**3 * Signal Processing4      *5      * @paramSignal Signal6      */7      Public voidhandle (Signal Signal) {8     }9}

Fourth, in the handle interface receiving the signal callback, initialize the JVM's Shutdownhook thread and register it with runtime, the sample code is as follows:

1 Private void Registershutdownhook () 2 {3         New Thread (new Shutdownhook (), "Shutdownhook-thread"); 4         runtime.getruntime (). Addshutdownhook (t); 5  }

The fifth step, after receiving the process exit signal, executes the exit operation of the virtual machine in the callback's handle interface, the sample code is as follows:

1 runtime.getruntime (). exit (0);

When the JVM exits, the underlying automatically detects if the user has registered for the Shutdownhook task, and if so, automatically executes the Run method of registering the hook, and the application only needs to perform the cleanup in Shutdownhook, as shown in the following example code:

1 classShutdownhookImplementsRunnable2 {3 @Override4          Public voidrun () {5System.out.println ("Shutdownhook Execute start ...");6                 Try {7TimeUnit.SECONDS.sleep (10);//simulate process operations before the app process exits8}Catch(interruptedexception e) {9 e.printstacktrace ();Ten                 } OneSystem.out.println ("Shutdownhook Execute End ..."); A                 } -}

Through the above steps, we can easily implement the security of the JVM exit, in addition, usually safe exit requires a time-out control mechanism, such as 30S, if the arrival time-out still does not complete the exit, then the shutdown script directly call kill-9 Force exit.

Precautions for using close hooks
    • The close hook is essentially a thread (also known as a hook thread), and for multiple closed hooks registered in a JVM they will execute concurrently, so the JVM does not guarantee their execution order, and because it is executed concurrently, it is likely that a race condition or deadlock is caused by improper code, in order to avoid this problem, It is strongly recommended to perform a series of operations in a hook.

    • The hook thread delays the JVM's shutdown time, which requires that the hook thread's execution time be reduced as much as possible during the writing of the hooks, avoiding time-consuming computations in the hook thread, waiting for user I/O, and so on.

    • The closure of the hook may be forced to interrupt execution, such as when the operating system shuts down, the operating system will wait for the process to stop, wait for timeout, the process is still not stopped, the operating system will be forced to kill the process, in such cases, the closure of the hook in the execution process is forced to abort.
    • In closing the hook, cannot perform the registration, remove the hook operation, the JVM will close the hook sequence after initialization, do not allow to add or remove the existing hooks, otherwise the JVM throws IllegalStateException.
    • The System.exit () cannot be called on the hook, otherwise the shutdown process of the JVM is stuck, but Runtime.halt () can be called.
    • The hook thread also throws an exception, and for an unhandled exception, the default exception handler for the thread handles the exception without affecting the other hook threads and the JVM quitting gracefully.
Summarize

In order to ensure the execution of asynchronous operations during the application restart process, to avoid forcing the exit of the JVM, we can actively notify the JVM to exit by closing the hooks, customizing the signal, and perform some cleanup of the application before the JVM shuts down, further guaranteeing that the application can safely exit.

JVM exits safely (how to gracefully shut down the Java service)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.