¿Por qué realmente necesitamos múltiples hilos de jefe mezquino?

Estoy realmente confundido sobre la cantidad de hilos para un grupo de jefes. No puedo entender un escenario en el que necesitamos más de un hilo jefe. En¿Necesitamos más de un hilo para el grupo de jefes? El creador de Netty dice que múltiples hilos de jefe son útiles si compartimos NioEventLoopGroup entre diferentes arranques de servidor, pero no veo la razón.

Considere este simple servidor 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();
}

En el ejemplo anterior, creo un bossGroup con 1 subproceso y workerGroup con 4 subprocesos y comparto ambos grupos de eventos a dos bootstraps diferentes que se unen a dos puertos diferentes (por ejemplo, 9000 y 9001). A continuación se muestra mi controlador:

@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();
}
}

En mi controlador anterior, a propósito mantengo ocupado el canal haciendo while (verdadero); Ahora, si inicio mi aplicación con el parámetro 9000, creará dos bootstraps del servidor que se unen en los puertos 9000 y 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

Ahora, si me conecto a ambos puertos y empiezo a enviar datos, el número máximo de conexiones que se pueden recibir es 4, lo que tiene sentido ya que he creado 4 subprocesos de trabajo y mantengo su canal ocupado sin cerrarlo:

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

También puedes hacer:

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

Lo que no entiendo es que tengo un subproceso de jefe y puedo conectarme a dos puertos con dos bootstraps de servidor. Entonces, ¿por qué necesitamos más de un subproceso principal (y, de forma predeterminada, el número de subprocesos principales es 2 * num_logical_processors)?

Gracias,

Respuestas a la pregunta(1)

Su respuesta a la pregunta