Netty-主動關閉Server


  工作中要能主動地關閉netty server端,下面的文章中的方法是好用的,記錄一下。

 

  原文地址:https://blog.csdn.net/wk52525/article/details/87896075

  1.主動關閉server

  • 如下面的代碼所示,這里啟動server時將ServerChannel的實例保存至靜態屬性,然后暴露一個closeServer()方法,直接調用ServerChannel的close()方法,此線程則會從阻塞狀態恢復,向下執行,進入finally代碼塊,退出server並清理相關資源。
package com.huoli.mj.rpc.server;
 
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public class NettyServer {
 
    private static Logger logger = LoggerFactory.getLogger(NettyServer.class);
    
    private static Channel serverChannel;
 
    /** 關閉當前server */
    public static void closeServer() {
        if (serverChannel != null) {
            logger.info("close server");
            serverChannel.close();
            serverChannel = null;
        }
    }
 
    /** 啟動server */
    private void start(int port) throws Exception {
        // 通過獨立線程啟動server
        Thread nettyServer = new Thread(() -> {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                        .childHandler(new DefaultServerChannelInitializer()).option(ChannelOption.SO_BACKLOG, 128)
                        .childOption(ChannelOption.SO_KEEPALIVE, true);
 
                // 綁定端口啟動成功
                ChannelFuture channelFuture = b.bind(port).sync();
                logger.info("start rpc server success with port:" + port);
                // 將ServerChannel保存下來
                serverChannel = channelFuture.channel();
                // 阻塞至channel關閉
                serverChannel.closeFuture().sync();
            } catch (Exception e) {
                logger.error("MJ netty server error", e);
            } finally {
                // 優雅關閉server線程及相關資源
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }
        });
        nettyServer.setName("netty-server-thread");
        nettyServer.setDaemon(true);
        nettyServer.start();
    }
}

  2.在ChannelHandler中關閉server

  • 在某些場景下,會需要在特定事件回調時主動關閉server端。下面代碼展示了在監聽到異常拋出事件時主動關閉server的操作。
  • 以下面代碼為例:ChannelHandler的事件回調方法中,ctx.close() 或 ctx.channel().close()只能關閉與某個客戶端連接的channel,而ctx.channel().parent()獲取到的是ServerChannel,所以調用ctx.channel().parent().close()才能關閉server,使server啟動線程從阻塞狀態恢復,從而在finally代碼塊中執行退出關閉操作。
package top.kylewang.netty.demo.second.server;
 
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public class TestSocketServerHandler extends ChannelInboundHandlerAdapter {
 
    private static final Logger logger = LoggerFactory.getLogger(TestSocketServerHandler.class);
 
    /** 監聽異常 */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        // 關閉serverChannel
        ctx.channel().parent().close();
    }

 


免責聲明!

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



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