与Netty和NIO高度并发的HTTP

Tob*_*ede 8 java concurrency http clojure netty

我正在使用示例Netty HTTP客户端代码,以便在并发的线程环境中发出http请求.

但是,我的系统在相当低的吞吐量下完全中断(有一些例外).

在几乎伪代码中:

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);
Run Code Online (Sandbox Code Playgroud)

在示例中,为了发出请求,我创建了一个ClientBootstrap,并从那里(通过一些箍)一个Channel来编写HTTPRequest.

这一切都有效,也很好.

但是,在同时发生的情况下,每个请求是否应该通过相同的环节?我认为这对我来说正在破坏的是什么.我应该以完全不同的方式重用连接或构建我的客户端吗?

另外:我在Clojure中这样做,如果这有任何区别的话.

Yan*_*hon 7

不,你做得对.但是,您必须保留对Channel实例的引用.一旦拥有该通道,只要它是打开的,您就不需要创建另一个引导程序.(如果这就是你正在做的事.)

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

class 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
            );
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

class ClientConnection.connect(String host,int port)

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();
    }
});
Run Code Online (Sandbox Code Playgroud)

所以,基本上,我只保留为参考bootstrapchannel,但前者几乎没有这行代码之外使用.

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

一旦连接了Channel实例,您只需要使用该实例,直到再次关闭它.一旦关闭,您可以回想起bootstrap再创建一个新的Channel.

就个人而言,我一开始觉得Netty有点难以理解,但是一旦掌握了它的工作原理,它就是Java中最好的NIO框架.IMO.

  • 如果你想建立另一个连接并利用现有的机器(底层的Netty NIO工作线程),`bootstrap`也会很有用. (3认同)