8

我正在研究示例 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);

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

这一切都有效并且很好。

但是,在并发情况下,每个请求都应该经过相同的循环吗?我认为这就是目前让我崩溃的原因。我应该重用连接还是以完全不同的方式构建我的客户端?

另外:我在 Clojure 中这样做,如果这有什么不同的话。

4

2 回答 2

7

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

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

类 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();
    }
});

bootstrap所以,基本上,我只保留对and的引用channel,但是前者几乎没有在这些代码行之外使用。

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

一旦你有一个连接的Channel实例,你只需要使用那个,直到你再次关闭它。关闭后,您可以bootstrap重新创建一个新的Channel

就我个人而言,一开始我觉得 Netty 有点难以理解,但是一旦你掌握了它的工作原理,它简直就是 Java 中最好的 NIO 框架。国际海事组织。

于 2011-03-31T04:00:48.007 回答
1

Netty 是在 JVM 中编写高并发 HTTP 服务的最佳方法,但它非常复杂且难以直接交互,尤其是在使用 Clojure 时。看看 Donkey,它提供与使用 Netty 作为后端的 Vert.x 的互操作。这种分层抽象出许多细微的低级细节,如果做错了,可能会导致服务不稳定。驴是相对较新的,所以还没有很多关于它的文档。查看此博客,其中包含一个开源项目,该项目使用 Donkey 在 Clojure 中实现了一个基本的新闻提要微服务。它详细介绍了架构、设计、编码和负载下的性能。

于 2021-03-27T17:57:03.777 回答