Netty 4 呼叫被阻止,简单的 Telnet 服务器

Netty 4 Calls being blocked , Simple Telnet Server

我正在尝试使用 Netty Telnet 服务器与 netty api 一起玩,以检查是否可以观察到真正的异步行为。

下面是正在使用的三个 类

TelnetServer.java

public class TelnetServer {

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
          EventLoopGroup bossGroup = new NioEventLoopGroup(1);
          EventLoopGroup workerGroup = new NioEventLoopGroup();
          try {
              ServerBootstrap b = new ServerBootstrap();
              b.group(bossGroup, workerGroup)
               .channel(NioServerSocketChannel.class)
               .handler(new LoggingHandler(LogLevel.INFO))
               .childHandler(new TelnetServerInitializer());


              b.bind(8989).sync().channel().closeFuture().sync();
          } finally {
              bossGroup.shutdownGracefully();
              workerGroup.shutdownGracefully();
          }
    }

}

TelnetServerInitializer.java

public class TelnetServerInitializer extends ChannelInitializer<SocketChannel> {

    private static final StringDecoder DECODER = new StringDecoder();
    private static final StringEncoder ENCODER = new StringEncoder();

    private static final TelnetServerHandler SERVER_HANDLER = new TelnetServerHandler();


    final EventExecutorGroup executorGroup = new DefaultEventExecutorGroup(2);

    public TelnetServerInitializer() {

    }

    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();


        // Add the text line codec combination first,
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        // the encoder and decoder are static as these are sharable
        pipeline.addLast(DECODER);
        pipeline.addLast(ENCODER);

        // and then business logic.
        pipeline.addLast(executorGroup,"handler",SERVER_HANDLER);
    }
}

TelnetServerHandler.java

/**
 * Handles a server-side channel.
 */
@Sharable
public class TelnetServerHandler extends SimpleChannelInboundHandler<String> {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // Send greeting for a new connection.
        ctx.write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
        ctx.write("It is " + new Date() + " now.\r\n");
        ctx.flush();
        ctx.channel().config().setAutoRead(true);
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, String request) throws Exception {
        // Generate and write a response.

        System.out.println("request = "+ request);

        String response;
        boolean close = false;
        if (request.isEmpty()) {
            response = "Please type something.\r\n";
        } else if ("bye".equals(request.toLowerCase())) {
            response = "Have a good day!\r\n";
            close = true;
        } else {
            response = "Did you say '" + request + "'?\r\n";
        }

        // We do not need to write a ChannelBuffer here.
        // We know the encoder inserted at TelnetPipelineFactory will do the conversion.
        ChannelFuture future = ctx.write(response);

        Thread.sleep(10000);
        // Close the connection after sending 'Have a good day!'
        // if the client has sent 'bye'.
        if (close) {
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

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

现在当我通过 telnet 客户端连接并发送命令 hello hello hello 三次时

在完成对 channelRead 的第一个响应之前,请求不会到达 channelRead 是否有任何方法可以使它完全异步,以便在套接字上可用时立即接收三个 hello。

Netty 对每个处理程序的每个传入读取最多使用 1 个线程,这意味着对 channelRead 的下一次调用只会在上一次调用完成后分派。这是大多数处理程序正确工作所必需的,包括以正确的顺序发回消息。如果计算量真的很复杂,另一种解决方案是为消息使用自定义线程池。

如果另一个操作是另一种连接,您也应该将其用作异步连接。只有每个部分都正确执行此操作,您才能获得异步。