Netty realize how gracefully exit mechanism and principle

Netty realize how gracefully exit mechanism and principle

Elegant process exit

Kill -9 PID caused problems

Often forced to kill a process on Linux via kill -9 pid way, this simple and efficient way, thus stopping many programs scripts often choose to use kill -9 pid way.

Whether it is Linux or windows of Kill -9 pid of taskkill / f / pid forced to withdraw from the process, will bring some side effects : application software in terms of its effect is equivalent to a sudden power failure can cause the following problems:

  1. Data in the cache has not yet persisted to disk, resulting in data loss;
  2. write file operation is in progress, there is no update is complete, quit suddenly, resulting in file corruption;
  3. Thread message queue request message received still not enough time to process, resulting in loss of the request message;
  4. When the database operation has been completed, such as account balance updates, ready to return a response message to the client, sends a message queue communication thread is still in line waiting to be sent, the process leading to the forced exit response message is not returned to the client, the client initiates retry timeout will bring repeat update problems;
  5. Other issues ...

JAVA elegant exit

Java elegant downtime is typically achieved by ShutdownHook registered the JDK, when the system receives an exit command, first of all marking system in the exit status, no longer receive new message, and then the backlog of messages processed, the final call interface resource recycling destruction, the last execution of each thread exits.

Netty realize how gracefully exit mechanism and principle

Usually need to have an elegant exit timeout control mechanisms, such as 30S, if the arrival time-out time is still not completed before the exit recycling and other operations by the downtime script called directly kill -9 pid, Force Quit.

Netty's how elegant exit

To achieve an elegant exit Netty, you first need to understand the process of the elegant common Java how to quit. Here we realize at first explain the principle elegant exit, combined with the actual code to explain. Finally, look how elegant exit of Netty.

Signals Introduction

Signal is at the level of an analog software interrupt mechanism, in principle, a process receives a signal from the processor receives an interrupt request can be said to be the same, it is interprocess mechanism for asynchronous communication. Linux command to kill an example, kill -s SIGKILL pid (ie kill -9 pid) immediately kill the specified process pid, SIGKILL signal is sent to pid process.

Correlation signal with a platform, a number of Linux platform support signal to terminate the process is as follows:

Netty realize how gracefully exit mechanism and principle

There are some differences in the Windows platform, some of the signal for example as follows: SIGINT (Ctrl + C interrupt), SIGILL, SIGTERM (kill software issued termination), SIGBREAK (Ctrl + Break interrupts).

Select signal: In order not to interfere with the normal operation of the signal, and can simulate Java asynchronous notification, on Linux we need to select a special signal . View signal by the description on the list, find SIGUSR1 and SIGUSR2 is to allow user-defined signal, we can choose SIGUSR2, in order to facilitate testing, on Windows we can choose SIGINT.

Elegant exit Java program

First look at common Java process flow diagram elegant exit:

Netty realize how gracefully exit mechanism and principle

1, when the application process is started, initialization Signal instance, its sample code is as follows:

Signal sig = new Signal(getOSSignalType());

Wherein the parameter Signal String to string constructor, i.e. semaphore name described in section 2.1.1.

2, to obtain a corresponding signal name based on the name of the operating system, as follows:

private String getOSSignalType()
 {
 return System.getProperties().getProperty("os.name").
		 toLowerCase().startsWith("win") ? "INT" : "USR2";
 }

Determines whether the windows operating system, if so selected SIGINT, receiving instructions Ctrl + C interrupts; USR2 otherwise select signal, receiving a SIGUSR2 (equivalent to kill -12 pid) instruction.

3, after the instantiation SignalHandler registered to the JDK Signal, upon receiving the Java process or kill -12 Ctrl + C the callback interface to handle, the following sample code:

Signal.handle(sig, shutdownHandler);

Wherein shutdownHandler achieved SignalHandler handle (Signal sgin) interface method, the following sample code:

Netty realize how gracefully exit mechanism and principle

4, the received signal handle callback interface, the JDK ShutdownHook thread initialization, and registers it in Runtime, the following sample code:

private void invokeShutdownHook()
 {
	Thread t = new Thread(new ShutdownHook(), "ShutdownHook-Thread");
	Runtime.getRuntime().addShutdownHook(t);
 }

5, after receiving the exit signal process is performed in a virtual machine exit callback handle interface, the following sample code:

Runtime.getRuntime().exit(0);

When a virtual machine exit, the bottom will automatically detect whether the user is registered ShutdownHook task, if any, will be automatically ShutdownHook pull the thread, the implementation of its Run method, users only need to perform the operation to release resources in ShutdownHook, the sample code below :

class ShutdownHook implements Runnable
{
	@Override
	public void run() {
		System.out.println("ShutdownHook execute start...");
		System.out.print("Netty NioEventLoopGroup shutdownGracefully...");
		try {
			TimeUnit.SECONDS.sleep(10);// 模拟应用进程退出前的处理操作 
		} catch (InterruptedException e) {
				e.printStackTrace();
		}
		System.out.println("ShutdownHook execute end...");
	System.out.println("Sytem shutdown over, the cost time is 10000MS");
		}
}

Here we were in a Windows environment for common Java elegant exit the program test, open CMD console, pull up the program to be tested as follows:

Start the process:

Netty realize how gracefully exit mechanism and principle

View thread information, find registered ShutdownHook thread does not start, in line with expectations:

Netty realize how gracefully exit mechanism and principle

In the console execute Ctrl + C, the process exits, the examples are as follows:

Netty realize how gracefully exit mechanism and principle

As shown above, ShutdownHook thread we define to be executed when the JVM exits, as a test program, it quits after sleep 10S, print information about the console as follows:

Netty realize how gracefully exit mechanism and principle

Below we summarize the technical points Java programs under a common elegant exit:

Netty realize how gracefully exit mechanism and principle

Netty's elegant exit

In a real project, as a high-performance asynchronous NIO Netty communications framework, the communications framework are often used as the base charge of the access protocols, the resolution and scheduling, for example, in a distributed RPC services and frameworks, often used as an internal Netty proprietary protocol based communications framework.

When the application process elegant exit, Netty as a communication framework also needs an elegant exit, the main reasons are as follows:

  1. NIO thread release as soon as possible, handles and other resources;
  2. If the batch did flush message needs to be accumulated in the transmission queue of the transmission completion message to be sent;
  3. Is write or read the news, we need to continue to deal with;
  4. Cron job set in NioEventLoop thread scheduler, or need to perform cleanup.

Here we look elegant exit Netty major operations and resource objects involved:

Netty realize how gracefully exit mechanism and principle

Netty elegant exit summed up the three-step operation:

  1. The status bit is set to ST_SHUTTING_DOWN NIO thread state, no new message processing (not allowed to send messages outside);
  2. Preprocessing operation before exiting: send message queue that has not transmitted or is transmitted from the transmitting end, the timer has expired or expired before exiting the task execution time-out completion, the registered user to exit Hook to complete the task execution thread NIO ;
  3. Release operation of resources: the release of all the Channel, to register multiplexer and closed, empty all queues and regular tasks of cancellation, and finally exit the NIO thread.

Here we look at how to achieve specific Netty's elegant exit:

Netty exit elegant interface and total entrance EventLoopGroup, calling its shutdownGracefully method can be, the relevant code is as follows:

bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();

The method of addition shutdownGracefully no parameters can also specify and exit timeout period, interfaces are defined as follows:

Netty realize how gracefully exit mechanism and principle

The next chapter shutdownGracefully works EventLoopGroup do explain in detail, combined with Java generic elegant exit mechanism, you can achieve an elegant exit Netty, the relevant pseudo-code is as follows:

// 统一定义 JVM 退出事件,并将 JVM 退出事件作为主题对进程内部发布 
// 所有需要优雅退出的消费者订阅 JVM 退出事件主题 
// 监听 JVM 退出的 ShutdownHook 被启动之后,发布 JVM 退出事件 
// 消费者监听到 JVM 退出事件,开始执行自身的优雅退出 
// 如果所有的非守护线程都成功完成优雅退出,进程主动退出 
// 如果到了退出的超时时间仍然没正常退出,则由停机脚本通过 kill -9 pid 强杀进程,强制退出

in conclusion

After the JVM ShutdownHook is triggered, all method calls shutdownGracefully EventLoopGroup instances are elegant exit. Because Netty itself has a better support to the elegant exit, it is relatively simple to implement.

I compiled most of the questions and answers plane architecture of some Internet companies java programmers involved in the interview made the document architecture and video materials free for everyone to share (including Dubbo, Redis, Netty, zookeeper, Spring cloud, distributed , high concurrency architecture and other technical data) can also get more attention interview information, save time we collected! Now free access into the group 571 617 441! !

Netty elegant exit Principle Analysis

Netty elegant exit relate to the thread group, thread, links, and other regular tasks, the underlying implementation details are very complex, here we come down to every level, by analyzing its source code to implement the principles.

NioEventLoopGroup

NioEventLoopGroup actually NioEventLoop thread group, its elegant exit is relatively simple, direct EventLoop traverse the array, the cycle call them shutdownGracefully method, source code is as follows:

Netty realize how gracefully exit mechanism and principle

NioEventLoop

Call NioEventLoop of shutdownGracefully method, the first is to modify the thread status is closed, its implementation in the parent class SingleThreadEventExecutor, their inheritance as follows:

Netty realize how gracefully exit mechanism and principle

SingleThreadEventExecutor of shutdownGracefully code is relatively simple, it is to modify the state of the thread bits should be noted that the need to make a judgment call when concurrent modification, if it is called by NioEventLoop itself, you do not need a lock, or need to lock, the code is as follows:

Netty realize how gracefully exit mechanism and principle

Under explain why lock, because shutdownGracefully a public way, anything that can get to NioEventLoop code can call it, in Netty, a business code usually do not require direct access NioEventLoop and operate it, but Netty made thicker to NioEventLoop package, it can not read the message, but also capable of performing regular tasks, and executing a user-defined task thread pool . So get NioEventLoop in the Channel method of opening out, which means that users will be able to get into the Channel, in theory, will perform shutdownGracefully there may be concurrent, so when elegant exit made concurrent protection.

After completion of the status modification, the rest of the operation is mainly conducted in NioEventLoop code is as follows:

Netty realize how gracefully exit mechanism and principle

We continue to look to achieve closeAll, its principle is to register on the selector of all Channel are closed, but some Channel is sending a message, yet not close, you need to do it later, the core code is as follows:

Netty realize how gracefully exit mechanism and principle

Cycle call the close method Channel Unsafe, let's jump to the Unsafe, a method of close analysis.

AbstractUnsafe

AbstractUnsafe the close method is mainly to do the following things:

  • Determining whether a message of the link currently being transmitted, if the operation to be packaged into eventLoop Task will be closed later re-executed:

Netty realize how gracefully exit mechanism and principle

  • The empty transmission queue no longer allowed to send a new message:

Netty realize how gracefully exit mechanism and principle

  • SocketChannel call the close method to close the link:

Netty realize how gracefully exit mechanism and principle

  • Calls pipeline of fireChannelInactive, triggering link Close notification event:

Netty realize how gracefully exit mechanism and principle

  • Finally, call deregister, canceled SelectionKey from the multiplexer:

Netty realize how gracefully exit mechanism and principle

So far, elegant exit process has been completed, does that mean NioEventLoop threads can be pulled out, it's not.

Here, just do a Channel closure and deregistration from the Selector summarized as follows:

  1. By inFlush0 to determine whether the current message being transmitted, if, Channel closing operation, into NIO thread execution task queue again later close () operation is performed;
  2. As it has been allowed to send a new message to join, send once the operation is complete, close on the implementation of the link, the link is triggered off event and unregister from the Selector.

Has been said before, NioEventLoop addition to I / O read and write, but also possesses the timing of task execution, execution ShutdownHook close, if at this time there are regular tasks that are due, even if Chanel has been closed, but still need to continue to execute threads You can not quit. Let's analyze the process flow under TaskQueue.

TaskQueue

After executing the NioEventLoop closeAll (), you need to call confirmShutdown to see whether it can withdraw its processing logic is as follows:

Queued execution TaskQueue Task, code is as follows:

Netty realize how gracefully exit mechanism and principle

Performs a registration to the NioEventLoop ShutdownHook, code is as follows:

Netty realize how gracefully exit mechanism and principle

Determine whether arrived at the designated timeout elegant exit, if reached, or after a timeout, then immediately exit code is as follows:

Netty realize how gracefully exit mechanism and principle

If the specified timeout period did not arrive, temporarily quit, every next 100MS detect whether a new task is added, there will continue to execute:

Netty realize how gracefully exit mechanism and principle

In confirmShutdown method, a number of mixed waste that has been treated shutdown () method, for example:

Netty realize how gracefully exit mechanism and principle

Calling the new shutdownGracefully series method, the determination condition is never satisfied, and therefore to have been abandoned shutdown-related processing logic, not analyze in detail.

So far, confirmShutdown method to explain finished, confirmShutdown returns true, NioEventLoop thread officially withdraw, Netty elegant exit is completed, the code is as follows:

Netty realize how gracefully exit mechanism and principle

This article is over! Like a friend of mine and look like little, thanks for the support! !

Guess you like

Origin blog.csdn.net/qwe123147369/article/details/91617033