Зачем нам действительно нужно несколько потоков нетти-боссов?

Я действительно смущен количеством потоков для группы боссов. Я не могу понять сценарий, когда нам нужно более одного потока босса. Внам нужно больше, чем один поток для группы боссов? создатель Netty говорит, что несколько потоков боссов полезны, если мы совместно используем NioEventLoopGroup между различными серверными загрузчиками, но я не вижу причины для этого.

Рассмотрим этот простой сервер Echo:

public class EchoServer {

private final int port;
private List<ChannelFuture> channelFutures = new ArrayList<ChannelFuture>(2);

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

public void start() throws Exception {

    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup(4);

    for (int i = 0; i != 2; ++i) {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class) // the channel type
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch)
                            throws Exception {
                        System.out.println("Connection accepted by server");
                        ch.pipeline().addLast(
                                new EchoServerHandler());
                    }
                });

        // wait till binding to port completes
        ChannelFuture f = b.bind(port + i).sync();
        channelFutures.add(f);
        System.out.println("Echo server started and listen on " + f.channel().localAddress());
    }

    for (ChannelFuture f : channelFutures)
        f.channel().closeFuture().sync();

    // close gracefully
    workerGroup.shutdownGracefully().sync();
    bossGroup.shutdownGracefully().sync();
}

public static void main(String[] args) throws Exception {
    if (args.length != 1) {
        System.err.println(
                "Usage: " + EchoServer.class.getSimpleName() +
                        " <port>");
        return;
    }
    int port = Integer.parseInt(args[0]);
    new EchoServer(port).start();
}

В приведенном выше примере я создаю bossGroup с 1 потоком и workerGroup с 4 потоками и разделяю обе группы событий на две разные загрузочные ловушки, которые связываются с двумя разными портами (например, 9000 и 9001). Ниже мой обработчик:

@ChannelHandler.Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {

@Override
public void channelRead(ChannelHandlerContext ctx,
                        Object msg)  throws Exception  {
    ByteBuf in = (ByteBuf) msg;
    System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8) + " from channel " + ctx.channel().hashCode());
    ctx.write(in);
}

@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
    System.out.println("Read complete for channel " + ctx.channel().hashCode());
    // keep channel busy forever
    while(true); 
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx,
                            Throwable cause) {
    cause.printStackTrace();
    ctx.close();
}
}

В моем описанном выше обработчике я намеренно поддерживаю занятость канала, выполняя while (true); Теперь, если я запусту свое приложение с параметром 9000, оно создаст две серверные загрузчики, которые будут привязаны к портам 9000 и 9001.

Echo server started and listen on /0:0:0:0:0:0:0:0:9090
Echo server started and listen on /0:0:0:0:0:0:0:0:9091

Теперь, если я подключаюсь к обоим портам и начинаю отправлять данные, максимальное количество соединений, которое может быть получено, равно 4, что имеет смысл, поскольку я создал 4 рабочих потока и поддерживаю их канал занятым, не закрывая его:

echo 'abc' > /dev/tcp/localhost/9000
echo 'def' > /dev/tcp/localhost/9000
echo 'ghi' > /dev/tcp/localhost/9001
echo 'jkl' > /dev/tcp/localhost/9000
echo 'mno' > /dev/tcp/localhost/9001 # will not get connected

Вы также можете сделать:

telnet localhost 9000 -> then send data "abc"
telnet localhost 9000 -> then send data "def"
telnet localhost 9001 -> then send data "ghi"
telnet localhost 9000 -> then send data "jkl"
telnet localhost 9001 -> # will not get connected

Чего я не понимаю, так это того, что у меня есть одна ветвь босса, и я могу подключиться к двум портам с двумя загрузками сервера. Итак, почему нам нужно более одного потока босса (и по умолчанию количество потоков босса равно 2 * num_logical_processors)?

Спасибо,

Ответы на вопрос(1)

Ваш ответ на вопрос