2013-04-03 56 views
0

我在下面的代碼中遇到了java.nio.channels.NotYetConnectedException,因爲我試圖寫入尚未打開的通道。正確的方式來淨化netty中的客戶端通道?

本質上,我擁有的是一個通道池,在該通道池中,如果某個通道閒置,我可以通過該通道池進行寫入,並且如果無法使用,則會創建一個新通道。我的問題是,當我創建一個新頻道時,當我調用連接時,頻道沒有準備好寫入,並且我不想在返回之前等待連接打開,因爲我不想阻止該線程。什麼是最好的方法來做到這一點?另外,我的檢索/返回渠道的邏輯是否有效?見下面的代碼。

我有一個簡單的連接池類似如下:

private static class ChannelPool { 
    private final ClientBootstrap cb; 
    private Set<Channel> activeChannels = new HashSet<Channel>(); 
    private Deque<Channel> freeChannels = new ArrayDeque<Channel>(); 
    public ChannelPool() { 
     ChannelFactory clientFactory = 
       new NioClientSocketChannelFactory(
         Executors.newCachedThreadPool(), 
         Executors.newCachedThreadPool()); 
     cb = new ClientBootstrap(clientFactory); 
     cb.setPipelineFactory(new ChannelPipelineFactory() { 
      public ChannelPipeline getPipeline() { 
       return Channels.pipeline(
         new HttpRequestEncoder(), 
         new HttpResponseDecoder(), 
         new ResponseHandler()); 
      } 
     }); 
    } 

    private Channel newChannel() { 
     ChannelFuture cf; 
     synchronized (cb) { 
      cf = cb.connect(new InetSocketAddress("localhost", 18080)); 
     } 
     final Channel ret = cf.getChannel(); 
     ret.getCloseFuture().addListener(new ChannelFutureListener() { 

      @Override 
      public void operationComplete(ChannelFuture arg0) throws Exception { 
       System.out.println("channel closed?"); 
       synchronized (activeChannels) { 
        activeChannels.remove(ret); 
       } 
      } 
     }); 
     synchronized (activeChannels) { 
      activeChannels.add(ret); 
     } 
     System.out.println("returning new channel"); 
     return ret; 
    } 

    public Channel getFreeChannel() { 
     synchronized (freeChannels) { 
      while (!freeChannels.isEmpty()) { 
       Channel ch = freeChannels.pollFirst(); 
       if (ch.isOpen()) { 
        return ch; 
       } 
      } 
     } 
     return newChannel(); 
    } 

    public void returnChannel(Channel ch) { 
     synchronized (freeChannels) { 
      freeChannels.addLast(ch); 
     } 
    } 
} 

我試圖用這個處理程序中,如下所示:

private static class RequestHandler extends SimpleChannelHandler { 

    @Override 
    public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) { 
     final HttpRequest request = (HttpRequest) e.getMessage(); 
     Channel proxyChannel = pool.getFreeChannel(); 
     proxyToClient.put(proxyChannel, e.getChannel()); 
     proxyChannel.write(request); 
    } 
} 
+0

看看http://stackoverflow.com/questions/30748424/how-to-create-channel-pool-in-netty – Peeyush 2015-06-11 14:29:41

回答

1

不會立即增加新的信道activeChannelsbootstrap.connect(..)之後,您必須將偵聽器添加到bootstrap.connect(..)返回的ChannelFuture,並將該頻道添加到添加的偵聽器中的activeChannels。這樣,getFreeChannel()將永遠不會獲得尚未連接的頻道。

因爲很可能activeChannels是空的,即使你叫newChannel()newChannel()將返回建立連接甚至更早),你必須決定如何在這種情況下做的。如果我是你,我會將getFreeChannel()的返回類型從Channel更改爲ChannelFuture,以便在空閒頻道準備就緒時收到通知。

+0

我不認爲你有任何想法,爲什麼我仍然得到'連接重置由同行'(見http://stackoverflow.com/questions/15818767/what-events-do-i-need-to-listen-to-in-order-to-reuse-a-client-connection-in-淨價)。 – jonderry 2013-04-04 22:29:14