[英]Highly concurrent HTTP with Netty and NIO
我正在研究示例 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 中这样做,如果这有什么不同的话。
不,你做对了。 但是,您必须保留对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(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();
}
});
所以,基本上,我只保留对bootstrap
和channel
的引用,但是在这些代码行之外几乎不使用前者。
注意:你应该只执行bootstrap.releaseExternalResources();
一次,当应用程序退出时。 就我而言,客户端发送一些文件,然后关闭通道并退出。
一旦你有一个连接的Channel
实例,你只需要使用那个,直到你再次关闭它。 关闭后,您可以调用bootstrap
以再次创建新Channel
。
就我个人而言,我觉得 Netty 一开始有点难以理解,但是一旦你掌握了它的工作原理,它简直就是 Java 中最好的 NIO 框架。 海事组织。
Netty 是在 JVM 中编写高并发 HTTP 服务的最佳方法,但它非常复杂且难以直接互操作,尤其是在使用 Clojure 时。 看看 Donkey,它提供与使用 Netty 作为后端的 Vert.x 的互操作。 这种分层抽象了许多细微的低级细节,如果做错了,可能会导致服务不稳定。 Donkey 相对较新,因此还没有很多关于它的文档。 查看这个博客,其中包含一个开源项目,该项目使用 Donkey 在 Clojure 中实现了一个基本的新闻提要微服务。 它详细介绍了架构、设计、编码和负载下的性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.