(二) netty服務端意外退出 之 優雅退出


最近看《netty進階之路》這本書,記一下筆記心得,以后逐步完善…………

服務端代碼

final Handler serverHandler = new Handler();
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();

try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup,workGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,100)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(serverHandler);
}
});
ChannelFuture future = b.bind(18080).sync();

} finally {
System.out.println("final");
bossGroup.shutdownGracefully().sync();
workGroup.shutdownGracefully().sync();
}

  運行結果套接字關閉、進程退出。具體原因進行分析.

 netty 啟動原理:

先反復驗證 :

 

 

屏蔽finally 中的關閉代碼 ,如上圖(才發現idea 這個小功能,可以看dump,這幾個小按鈕也是功能強大) ,打開后可以發現有5個線程, 其中有3個daemon(守護線程) ,守護線程決定不了程序的結束,先不管。還有NioEventLoopGroup 和DestroyJavaVM , 這個DestroyJavaVm 好像是程序結束時銷毀虛擬機用的,現在只有NioEventLoopGroup阻塞了進程, 上述finally 中剛好有2個關閉Group的操作,所以這時候程序退出。

  以上是結果 , 說明在bind操作,會進行端口綁定,同時有同步阻塞。 在finally執行group.shutdownGracefully(),會關閉tcp接入線程池(bossGroup)和處理io工作線程池(workGroup)。

  如何防止netty服務斷意外退出:

  不優雅關閉group肯定是不行的,那程序只能暴力kill,會導致消息處理異常。具體操作方法如下

    程序監聽NioServerSocketChannel的關閉事件,同時阻塞mian函數:

    

 ChannelFuture future = b.bind(18080).sync();
            future.channel().closeFuture().sync();

  main函數一直阻塞,后續finally不被執行,程序不會退出。

  這樣貌似解決了問題,但是最近發現在業務系統中激活此服務后,主調用線程被阻塞了,也就是業務系統被卡住了…… 

  將代碼進行如下修改,服務端啟動后注冊監聽關閉事件,待服務關閉異步調用shutdownGracefull釋放資源,這樣調用方線程可以快速返回。

            ChannelFuture future = b.bind(18080).sync();
            future.channel().closeFuture(). addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    bossGroup.shutdownGracefully().sync();
                    workGroup.shutdownGracefully().sync();
                }
            });
        } finally {
            System.out.println("final");
//            bossGroup.shutdownGracefully().sync();
//            workGroup.shutdownGracefully().sync();
        }

  方法二:jvm的shutDownHook

    Runtime.getRuntime().addShutdownHook(new Thread(
                    ()->{
                        System.out.println("shut down Hook execute start ^");
                        try{
                            TimeUnit.SECONDS.sleep(3);
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                        System.out.println("shut down Hook execute end ^");
                    },""
            ));
            TimeUnit.SECONDS.sleep(7);
            System.out.println("System.exit ^");
            System.exit(0);

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM