2015-12-14 94 views
2

我真的很困惑老闆組的線程數量。我無法弄清楚我們需要多個boss線程的場景。在do we need more than a single thread for boss group? Netty的創建者說,如果我們在不同的服務器引導程序之間共享NioEventLoopGroup,那麼多個Boss線程是有用的,但我沒有看到它的原因。爲什麼我們真的需要多個netty boss線程?

考慮這個簡單的回聲服務器:

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

在上面的示例中,創建了1個線程和workerGroup與4個線程一個bossGroup和共享結合兩個不同的端口都事件組以兩種不同的自舉(例如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 

我做什麼不明白的是,我有一個老闆線程,我可以用兩個服務器引導程序連接到兩個端口。那麼爲什麼我們需要多個boss線程(並且默認情況下,#boss線程是2 * num_logical_processors)?

感謝,

+0

如果答案有幫助,請將其標記爲已接受。 – Suvitruf

回答

2

了Netty的創造者說,如果我們不同的服務器之間白手起家共享 NioEventLoopGroup多線程的老闆是有用的,但我沒有看到 的原因吧。

正如Norman Maurer所說,這不是必要的,但它非常有用。

如果您爲兩個不同的引導程序使用1個線程,則意味着您無法同時處理與此引導程序的連接。所以在非常糟糕的情況下,當boss線程只處理一個引導程序的連接時,連接到另一個永遠不會被處理。

相同的工人EventLoopGroup

+0

所以一個boss線程可以處理多個連接,但不能同時處理?而且,有多個boss線程是很有用的(例如,在一個Web服務器中,我們期望多個同時連接?)另外,我的理解或工作線程是否正確?謝謝。 – BestCoderEver

+0

@BestCoderEver老闆線程處理連接並將處理傳遞給工作線程。是的,有多個boss線程是很有用的。但不需要太多,因爲一般工作者線程比老闆線程工作的時間更長。 – Suvitruf