我正在为 Web 应用程序构建一个简单且最快的压力测试工具。要求:来自单个节点的最大输出 http 请求(例如,普通获取)。
我们之前使用过netty,我选择它来编写这个简单的测试。这非常简单,我只完成了 4 个扩展 netty api 的小类(代码在这里),它在 localhost 开发机器(linux)上提供了大约 30K rps。
主要限制是传出连接限制(Linux 中的打开文件/套接字限制),在我的机器上大约为 30-40K。你会遇到java.net.BindException
这种情况。因此,您必须手动限制传出 netty 连接的数量,以防止达到限制时性能下降。
我用计数器实现了这个限制,在第一个版本中,我增加了它SimpleChannelUpstreamHandler.channelConnected
并减少了它future.getChannel().getCloseFuture().addListener
(参见代码,那些地方的注释)它没有工作:连接没有按预期增加并且计数器失败。
只有在我把增量放在附近之后bootstrap.connect
:
connected.incrementAndGet();
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
并减少SimpleChannelUpstreamHandler.messageReceived
:
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
// the same here - decrementing connections here is not fully fair but works!
connected.decrementAndGet();
e.getChannel().close();
}
-它开始工作了。唯一的问题 - 这有点不公平,因为您可以增加计数器但无法连接或减少并且在它之后无法断开连接。
那么,为什么计数器在正确的版本中不起作用?
更新:按照建议尝试,inc/dec in SimpleChannelUpstreamHandler.channelConnected
:
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
// by logic you should count connection here, but in practice - it doesn't work
connected.incrementAndGet();
ctx.getChannel().getCloseFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
connected.decrementAndGet();
}
});
e.getChannel().write(GET);
sent.incrementAndGet();
}
没有用,再次发送>连接的不可预测的数字,例如:
client1 stat: connected= 0, sent= 0, ERRORS: timeouts= 0, binds= 0, connects=0
client1 stat: connected= 11, sent= 4990, ERRORS: timeouts= 0, binds= 0, connects=0
client1 stat: connected= 1, sent= 8591, ERRORS: timeouts= 0, binds= 0, connects=0
client1 stat: connected= 459, sent=13064, ERRORS: timeouts= 0, binds= 5, connects=0
client1 stat: connected= 1545, sent= 7234, ERRORS: timeouts= 0, binds= 115, connects=0
client1 stat: connected= 0, sent=10037, ERRORS: timeouts= 0, binds= 80, connects=0
萨德夫