2011-03-28 108 views
8

我正在通过example Netty HTTP Client code工作,以便在并发的线程环境中发出http请求。高并发HTTP与Netty和NIO

但是,我的系统在吞吐量相当低的情况下完全中断(有大量例外)。

几乎在伪代码:

ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory()) 
bootstrap.setPipelineFactory(new HttpClientPipelineFactory()); 

ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)); 
Channel channel = future.awaitUninterruptibly().getChannel(); 

HttpRequest request = new DefaultHttpRequest(); 
channel.write(request); 

在这个例子中,使我创造一个ClientBootstrap的请求,并从那里(通过几个铁圈)频道写的HTTPRequest。

这一切工作,并很好。

但是,在一个并发的情况下,是否每个请求都应该经历相同的箍?我认为那是目前对我而言的事情。我应该以完全不同的方式重用连接或构建我的客户吗?

另外:我在Clojure做这个,如果这样做有什么区别的话。

+0

也许你应该使用https://github.com/ztellman/aleph? – PheliX 2011-03-28 12:35:21

+0

你有aleph的经验吗?我尝试了另一个异步clojure http客户端,但它不能在我需要维持的吞吐量级别上工作。 – 2011-03-29 02:53:07

回答

7

不,你正在做的事情正确。但是,您必须保留对您的实例的引用。一旦你拥有了这个频道,只要它是开放的,你就不需要创建另一个引导程序。 (如果这是你在做什么。)

这是我在最近的一个项目中使用:

类ClientConnection(构造函数)

// Configure the client. 
bootstrap = new ClientBootstrap(
    new NioClientSocketChannelFactory(
     Executors.newCachedThreadPool(), 
     Executors.newCachedThreadPool() 
    ) 
); 

// Set up the pipeline factory. 
bootstrap.setPipelineFactory(
    new ChannelPipelineFactory() { 
     public ChannelPipeline getPipeline() throws Exception { 
      return Channels.pipeline(
       // put your handlers here 
      ); 
     } 
    } 
); 

类ClientConnection.connect(字符串主机,int端口)

if (isConnected()) { 
    throw new IllegalStateException("already connected"); 
} 

// Start the connection attempt. 
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)); 

channel = future.awaitUninterruptibly().getChannel(); 

// Wait until the connection is closed or the connection attempt fails. 
channel.getCloseFuture().addListener(new ChannelFutureListener() { 
    @Override 
    public void operationComplete(ChannelFuture future) throws Exception { 
     new Thread(new Runnable() { 
      public void run() { 
       // Shut down thread pools to exit 
       // (cannot be executed in the same thread pool! 
       bootstrap.releaseExternalResources(); 

       LOG.log(Level.INFO, "Shutting down"); 
      } 
     }).start(); 
    } 
}); 

所以,基本上,我只保留对bootstrapchannel的引用,但前者几乎不用于这些代码行之外。

注意:在应用程序退出时,您应该只执行一次bootstrap.releaseExternalResources();。在我的情况下,客户端发送一些文件,然后关闭通道并退出。

一旦你有一个连接的Channel实例,你只需要使用该实例,直到你再次关闭它。一旦关闭,您可以调用bootstrap再次创建新的Channel。我个人认为Netty起初有点难以理解,但是一旦掌握了它的工作原理,它就是Java中最好的NIO框架。 IMO。

+3

如果你想创建另一个连接并利用现有机器(底层Netty NIO工作线程),'bootstrap'也会很有用。 – 2011-04-06 00:02:14