Warum brauchen wir wirklich mehrere Netty Boss-Threads?

Ich bin wirklich verwirrt über die Anzahl der Threads für eine Bossgruppe. Ich kann mir kein Szenario vorstellen, in dem wir mehr als einen Boss-Thread benötigen. Im Brauchen wir mehr als einen Thread für die Bossgruppe? Der Schöpfer von Netty sagt, dass mehrere Boss-Threads nützlich sind, wenn wir NioEventLoopGroup zwischen verschiedenen Server-Bootstraps teilen, aber ich sehe den Grund dafür nicht.

Betrachten Sie diesen einfachen Echo-Server:

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

Im obigen Beispiel erstelle ich eine bossGroup mit 1 Thread und eine workerGroup mit 4 Threads und teile beide Ereignisgruppen mit zwei verschiedenen Bootstraps, die an zwei verschiedene Ports gebunden sind (z. B. 9000 und 9001). Unten ist mein Handler:

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

In meinem Handler oben halte ich den Kanal absichtlich mit while (true) beschäftigt. Wenn ich meine App jetzt mit Parameter 9000 starte, werden zwei Server-Bootstraps erstellt, die an Port 9000 und 9001 gebunden sind.

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

Nun, wenn ich eine Verbindung zu beiden Ports herstelle und mit dem Senden von Daten beginne, können maximal 4 Verbindungen empfangen werden. Dies ist sinnvoll, da ich 4 Worker-Threads erstellt und deren Kanal belegt habe, ohne ihn zu schließen:

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

Sie können auch:

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

was ich nicht verstehe, ist, ich habe einen Chefthread und ich bin in der Lage, mit zwei Server-Bootstraps eine Verbindung zu zwei Ports herzustellen. Warum brauchen wir also mehr als einen Boss-Thread (und standardmäßig ist die Anzahl der Boss-Threads 2 * num_logical_processors)?

Vielen Dank

Antworten auf die Frage(2)

Ihre Antwort auf die Frage