如何阻止netty bootstrap监听和接受新的连接

时间:2016-06-07 09:07:00

标签: java netty

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import sun.misc.Signal;
import sun.misc.SignalHandler;

import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

public class ReusePortServer {
  private final int port;
  private List<Channel> bindingChannels = new LinkedList<>();

  public ReusePortServer(int port) {
    this.port = port;
  }

  private void initSignals() {
    Signal.handle(new Signal("BUS"), new SignalHandler() {
      @Override public void handle(Signal signal) {
        System.out.println("signal arrived");
        closeChannels();
      }
    });
  }

  synchronized private void closeChannels() {
    for (Channel channel : bindingChannels) {
      channel.close();
    }

    bindingChannels.clear();
  }

  synchronized private void registerChannel(Channel channel) {
    bindingChannels.add(channel);
  }

  public void start() throws Exception {
    initSignals();

    EventLoopGroup group = new EpollEventLoopGroup();
    try {
      ServerBootstrap b = new ServerBootstrap();
      b.group(group)
              .channel(EpollServerSocketChannel.class)
              .option(EpollChannelOption.SO_REUSEPORT, true)
              .localAddress(new InetSocketAddress(port))
              .childHandler(new ChannelInitializer<SocketChannel>(){
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                  ch.pipeline().addLast(new ReusePortHandler());
                  registerChannel(ch);
                }
              });

      for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
        System.out.println(e.toString());
      }
      ChannelFuture f = b.bind().sync();
      log(String.format("%s started and listen on %s", ReusePortServer.class.getName(), f.channel().localAddress()));
      // registerChannel(ch);  // ---------------I also tried to register this channel, but after my signaling, it closes my client's connection, rather than keeping it.
      f.channel().closeFuture().sync();
    } finally {
      group.shutdownGracefully().sync();
    }
  }

  private final static SimpleDateFormat datefmt = new SimpleDateFormat("HH:mm:ss ");

  public static void log(final String msg) {
    System.out.print(datefmt.format(new Date()));
    System.out.println(msg);
    System.out.flush();
  }

  public static void main(final String[] args) throws Exception {
    int port = 12355;
    new ReusePortServer(port).start();
  }
}

嗨,我正在寻找一种方法来阻止netty在服务器套接字上监听和接受,但要完成当前连接上的任何正在进行的工作。

我遇到了以下问题: How to stop netty from listening and accepting on server socket

并根据它,我写了上面的代码,它接收信号(kill -7)来完成结束。

但结果不是预期的,它会关闭tcp连接,netty仍然可以接受新的连接。

我是否使用正确的停止网络方式来收听和接受?

这里有什么问题?

2 个答案:

答案 0 :(得分:2)

您应该像这样关闭ServerChannel:

ChannelFuture f = b.bind().sync();
// Call this once you want to stop accepting new connections.
f.channel().close().sync();

答案 1 :(得分:0)

我花了大约两天时间来解决这个问题。我试试这个,它对我有用:

首先,我宣布:

static ChannelFuture future;

然后,当我绑定端口时,我分配了未来的变量:

ServerBootstrap b = new ServerBootstrap(); 
b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ServerInitializer())
                .option(ChannelOption.SO_BACKLOG, NetUtil.SOMAXCONN)
                .childOption(ChannelOption.SO_KEEPALIVE, true);

future =  b.bind(WS_PORT).sync();

最后,我在Web应用程序停止时向处理程序事件添加了一个函数。

@PreDestroy
void shutdownWorkers() throws InterruptedException {
    future.channel().close().sync();
}