【问题标题】:Netty concurrency and "Connection reset by peer"Netty 并发和“对等连接重置”
【发布时间】:2011-10-25 00:49:41
【问题描述】:

我已经构建了以下简单的服务器,我正在使用ab 对其进行压力测试。 如果我运行 ab 发出 3000 个总请求(300 个并发),它就可以工作。如果我再次运行它,它会显示:

apr_socket_connect(): Connection reset by peer (54) 

如果在此错误之后我尝试使用 curl 发出单个请求而不重新启动服务器,它可以工作。如果我再次运行ab,它会显示相同的错误。 它似乎无法处理太多的并发连接。代码下方:

public static void main(String[] args) throws Exception {

        ServerBootstrap bootstrap = new ServerBootstrap(
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            @Override
            public ChannelPipeline getPipeline() throws Exception {
                return Channels.pipeline(new StringEncoder(), new MyServerHandler());
            }
        });

        bootstrap.bind(new InetSocketAddress(9090));
        System.out.println("Running");
}

这里是处理程序:

public class MyServerHandler extends SimpleChannelUpstreamHandler {

    private static AtomicLong request = new AtomicLong();

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
            throws Exception {  
        ChannelFuture channelFuture = e.getChannel().write("This is request #" + request.incrementAndGet() + "\n");
        channelFuture.addListener(ChannelFutureListener.CLOSE);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
            throws Exception {
        System.out.println(e.getCause());
        e.getChannel().close();
    }

}

如您所见,它非常简单,它只显示处理的请求总数。 有什么建议吗?

谢谢

【问题讨论】:

    标签: sockets concurrency nio netty


    【解决方案1】:

    'Connection reset by peer' 通常意味着你已经写入了一个已经被另一端关闭的连接。换句话说,应用程序协议错误。您在后续读取或写入时会收到错误本身。

    【讨论】:

    • 我没有得到服务器的任何异常,并且通过阅读我附加的源代码,我在实际发送消息之前不会关闭连接。请注意,这个问题只发生在大量并发请求的情况下。也许我错过了什么。
    • @Mark 我认为您需要再次阅读我的答案。您在某处遇到异常,否则您将不会发布,我确实说过“在另一端关闭”。
    • 你不能打开新的套接字。 ulimit -n 说什么?
    • @Slartibartfast 他已经打开了套接字。这就是他如何获得已重置的连接。这与“连接被拒绝”、“连接超时”等不同。
    • @EJP 我面临着某种相关的问题——简单的服务器负载 Netty 从它的内部抱怨“连接重置”。这是随机发生的,有时有效,有时无效。对于 500 个后续请求,它确实在 10 个案例中的 10 个情况下工作。对于 1000 个后续调用,它会因一个连接重置和 java.nio.channels.ClosedChannelException 而失败。我没有在客户端代码中明确关闭通道,那么它在哪里关闭?以及为什么会发生连接重置?
    【解决方案2】:

    我没有立即发现任何问题,但您可以尝试以下方法以获取更多信息:

    1. 覆盖 channelClosed 并输出一些内容,以便您 100% 确定 Netty 至少尝试关闭频道。
    2. 使用 jvisualvm 查看运行服务器的 JVM;您应该能够看到线程以及它们是否处于活动状态。
    3. channelConnected 上向System.out 服务器端写一些东西,这样你就知道你的连接已经走到了这一步(尤其是第二次运行)。
    4. 当您第二次运行ab 时,每次连接尝试都会出现错误,还是仅出现一些错误?

    我觉得奇怪的是它似乎第一次起作用,但之后就不行了。请记住,这可能不是 Netty(甚至是 JVM)问题,而是操作系统以某种方式限制了连接尝试。

    我用自己的Netty测试服务器做了一些测试,发现启动大批量并发连接会产生不可预知的结果(大多数会连接,有些会失败,但总是不同的比例)。到目前为止,我还没有弄清楚为什么会这样(还),但我怀疑是我的操作系统拒绝连接而不是 Netty。

    【讨论】:

      猜你喜欢
      • 2016-10-12
      • 1970-01-01
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-30
      • 1970-01-01
      相关资源
      最近更新 更多