Netty:当服务器没有数据返回时,如何异步等待?

时间:2012-01-09 13:38:34

标签: java netty

首先,感谢优秀的nio框架 - Netty。

我们的应用程序包括客户端和服务器部件,它们使用套接字连接进行通信并发送protobuf消息。客户端和服务器都是使用OIO编写的。 我正在基于netty框架将当前代码移动到nio。目前我的服务器实现有问题:我还没有找到如何使用netty的工作线程处理处理程序。

有简化的代码:

ServerBootstrap bootstrap = new ServerBootstrap(
  new NioServerSocketChannelFactory(
    Executors.newCachedThreadPool(),
    Executors.newCachedThreadPool(),
    Runtime.getRuntime().availableProcessors()
  )
);

// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
  public ChannelPipeline getPipeline() throws Exception {
    final ChannelPipeline pipeline = pipeline();
    // decoder
    pipeline.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
    pipeline.addLast("protobufDecoder", new ProtobufDecoder(LogServerProto.Request.getDefaultInstance()));
    // Encoder
    pipeline.addLast("protobufVarint32LengthFieldPrepender", new ProtobufVarint32LengthFieldPrepender());
    pipeline.addLast("protobufEncoder", new ProtobufEncoder());
    // handler
    pipeline.addLast("handler", new SimpleChannelUpstreamHandler() {
      @Override
      public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent event) throws Exception {
        logger.info("handleClientSocket in thread " + Thread.currentThread().getName());
        final MessageLite request = (MessageLite) event.getMessage();
        final MessageLite batch = storage.readBatch(request);
        if (batch != null) {
          event.getChannel().write(batch);
        } else {
          storage.registerListener(new Storage.StorageListener() {
            @Override
            public void onSaveBatch() {
              storage.removeListener(this);
              logger.info("Send upstream in thread " + Thread.currentThread().getName());
              event.getChannel().getPipeline().sendUpstream(event);
            }
          });
        }
      }
    });
    return pipeline;
  }
});

bootstrap.bind(new InetSocketAddress("localhost", 7000));

服务器接受来自客户端的请求(protobuf消息)。然后服务器向'storage'询问'批处理'。存储返回一个对象,如果当前没有批处理,则返回null。如果批处理非空 - 一切正常,但如果批处理不可用,服务器应在将批处理添加到存储时将其返回到客户端。 因此,我正在注册StorageListener,当批处理添加到存储时调用StorageListener(注意:批处理从分离的线程'storage-writing-thread'添加到存储中)。 StorageListener使用旧的'request'对象向上游发送,管道处理得很好,我的“处理程序”将响应(批处理)写入通道。看起来一切正常,但所有这些任务都在'storage-writing-thread'线程中处理。在这种情况下,如何更新监听器以处理netty的工作线程中的“处理程序”?

1 个答案:

答案 0 :(得分:0)

如果我正确地解决了你的问题,你正在寻找一种方法可以在结果可用时给出结果,为此,你需要有一个有效的线程,直到数据可用并给出回到结果。在您的情况下,存储类可以实现一个线程。

您不应该在工作线程中等待,也不需要在该线程中执行响应。要从服务器到客户端编写任何内容,您将需要访问客户端的通道。所以你需要的是将通道作为参数传递给你的线程并从该线程发送结果。