2013-07-29 22 views
1

我是Netty的新手。我正在使用「Netty 3.6.2.Final」。我創建了一個與遠程服務器通信的Netty客戶端(MyClient)(該服務器實現了基於TCP的自定義協議)。我爲每個MyClient實例(在構造函數中)創建一個新的ClientBootstrap實例。 我的問題是,如果我在MyClient的所有實例中共享「NioClientSocketChannelFactory」工廠對象,那麼何時/如何釋放與「NioClientSocketChannelFactory」相關的所有資源?換句話說,因爲我的Netty客戶端運行在一個運行24x7的JBOSS容器中,我應該通過調用「bootstrap.releaseExternalResources();」來釋放所有的資源,以及何時/我該在哪裏這樣做?Netty:在多個Netty客戶端之間共享NioClientSocketChannelFactory的正確方式是什麼

更多信息:我的Netty客戶端在JBOSS容器內的兩個場景中調用。首先,在for循環每次用傳遞需要被髮送到遠程服務器的字符串的無窮大(以類似於下面的代碼效果)

for(; ;){ 
    //Prepare the stringToSend 
    //Send a string and receive a string 
String returnedString=new MyClient().handle(stringToSend); 
} 

另一個方案是我的Netty客戶端與每個併發線程中調用線程調用「new MyClient()。handle(stringToSend);」。

我已經給出了下面的骨架代碼。它與Netty網站上的TelnetClient示例非常相似。

MyClient

import org.jboss.netty.bootstrap.ClientBootstrap; 
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; 
public class MyClient { 
    //Instantiate this only once per application 
    private final static Timer timer = new HashedWheelTimer(); 

    //All below must come from configuration 
    private final String host ="127.0.0.1"; 
    private final int port =9699; 
    private final InetSocketAddress address = new InetSocketAddress(host, port); 
    private ClientBootstrap bootstrap; 

    //Timeout when the server sends nothing for n seconds. 
     static final int READ_TIMEOUT = 5; 

     public MyClient(){ 
      bootstrap = new ClientBootstrap(NioClientSocketFactorySingleton.getInstance()); 
     } 

    public String handle(String messageToSend){ 
     bootstrap.setOption("connectTimeoutMillis", 20000); 
      bootstrap.setOption("tcpNoDelay", true); 
      bootstrap.setOption("keepAlive", true); 
      bootstrap.setOption("remoteAddress", address); 
     bootstrap.setPipelineFactory(new MyClientPipelineFactory(messageToSend,bootstrap,timer)); 

     // Start the connection attempt. 
      ChannelFuture future = bootstrap.connect(); 

      // Wait until the connection attempt succeeds or fails. 
      channel = future.awaitUninterruptibly().getChannel(); 


      if (!future.isSuccess()) { 
       return null; 
      } 

      // Wait until the connection is closed or the connection attempt fails. 
      channel.getCloseFuture().awaitUninterruptibly(); 

      MyClientHandler myClientHandler=(MyClientHandler)channel.getPipeline().getLast(); 
      String messageReceived=myClientHandler.getMessageReceived(); 
     return messageReceived; 
    } 
} 

的Singleton NioClientSocketChannelFactory

public class NioClientSocketFactorySingleton { 
private static NioClientSocketChannelFactory nioClientSocketChannelFactory; 

private NioClientSocketFactorySingleton() { 
} 

public static synchronized NioClientSocketChannelFactory getInstance() { 
    if (nioClientSocketChannelFactory == null) { 
     nioClientSocketChannelFactory=new NioClientSocketChannelFactory(
      Executors.newCachedThreadPool(), 
      Executors.newCachedThreadPool()); 
    } 
    return nioClientSocketChannelFactory; 
} 

    protected void finalize() throws Throwable { 
    try{ 
    if(nioClientSocketChannelFactory!=null){  
     // Shut down thread pools to exit. 
     nioClientSocketChannelFactory.releaseExternalResources(); 
    } 
    }catch(Exception e){ 
    //Can't do anything much 
    } 
    } 
} 

MyClientPipelineFactory

public class MyClientPipelineFactory implements ChannelPipelineFactory { 

    private String messageToSend; 
    private ClientBootstrap bootstrap; 
    private Timer timer; 
    public MyClientPipelineFactory(){ 

    } 
    public MyClientPipelineFactory(String messageToSend){ 
     this.messageToSend=messageToSend; 
    } 

    public MyClientPipelineFactory(String messageToSend,ClientBootstrap bootstrap, Timer timer){ 
     this.messageToSend=messageToSend; 
     this.bootstrap=bootstrap; 
     this.timer=timer; 
    } 

     public ChannelPipeline getPipeline() throws Exception { 

      // Create a default pipeline implementation. 
      ChannelPipeline pipeline = pipeline(); 

      // Add the text line codec combination first, 
      //pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); 
      pipeline.addLast("decoder", new StringDecoder()); 
      pipeline.addLast("encoder", new StringEncoder()); 

      //Add readtimeout 
      pipeline.addLast("timeout", new ReadTimeoutHandler(timer, MyClient.READ_TIMEOUT)); 

      // and then business logic. 
      pipeline.addLast("handler", new MyClientHandler(messageToSend,bootstrap)); 


      return pipeline; 
     } 
} 

MyClientHandler

public class MyClientHandler extends SimpleChannelUpstreamHandler { 

    private String messageToSend=""; 
    private String messageReceived=""; 


    public MyClientHandler(String messageToSend,ClientBootstrap bootstrap) { 
     this.messageToSend=messageToSend; 
     this.bootstrap=bootstrap; 
    } 

    @Override 
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e){ 
     e.getChannel().write(messageToSend); 
    } 

    @Override 
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e){ 
     messageReceived=e.getMessage().toString(); 
    //This take the control back to the MyClient 
    e.getChannel().close(); 
    } 

    @Override 
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { 
     // Close the connection when an exception is raised. 
     e.getChannel().close(); 

    } 


} 

回答

0

您應該只調用releaseExternalResources()一旦你確定你不需要它了。例如,當應用程序停止或取消部署時。