1

我正在为 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

萨德夫

4

2 回答 2

0

您需要增加 ChannelFutureListener 中发送的计数,该计数被添加到从 write(...) 操作返回的 ChannelFuture 中。否则,即使写入未决,您也会增加它。

于 2013-04-27T17:41:54.273 回答
0

一个理论。

在您的原始版本中,您减少所有连接尝试的连接计数器,如果失败了。如果您在channelConnected () 中增加计数器并向 ChannelCloseFuture 添加一个递减侦听器,那么我想您会得到更好的结果。

这是因为

boostrap.connect().getChannel().getCloseFuture(...)

将始终调用 operationComplete,即使通道从未连接过。

更新:

确保只计算连接的通道。在 STressClientHandler 的 channelConnected() 回调中:

    connected.incrementAndGet();
    ctx.getChannel().getCloseFuture().addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
             connected.decrementAndGet();
        }
    });
于 2013-04-24T08:50:48.150 回答