【问题标题】:TCP client socket filling up heapTCP 客户端套接字填满堆
【发布时间】:2015-06-24 16:23:34
【问题描述】:

使用 java 套接字库,我看到的是,当服务器接受 tcp 连接但未从缓冲区读取数据时,同时我们的客户端不断抽取大量数据,客户端堆大小增长到最大可用并粉碎客户端应用。 无论如何我可以限制套接字缓冲区大小或使用该堆的任何内容,如果违反,连接被终止?这样客户端可以检测到客户端检测到连接消失了

客户端;

  this.socket = new Socket(server, port);
  this.socket.setKeepAlive(true);
  this.outwriter = new OutputStreamWriter(this.socket.getOutputStream());
  this.outwriter.write(o.toString()); 

服务器端;

conn = serverSocket.accept();

【问题讨论】:

    标签: java sockets tcp serversocket


    【解决方案1】:

    您可以使用 socket.setSendBufferSize()。

    虽然这将有助于测试您的理论,正如@EJP 所提到的,堆泄漏不会是由于发送缓冲区被填满。在这种情况下,写操作将返回错误。

    【讨论】:

    • 他确实可以,但不能解决这个问题。
    • @EJP。是的。我同意。我会留下答案。让 OP 使用它并测试他的理论
    • 写操作会阻塞,不会返回错误。我看不出使用不相关的设置会如何测试任何东西。
    • 据我所知,这无济于事,因为它会限制速度。如果连接打开,客户端会获取大量数据并将数据推送到服务器。所以我应该要么关闭连接,要么能够检查客户端中的当前缓冲区大小,然后跳过 socket.write
    • @East2West 唯一可以做到这一点的方法是通过 NIO。但是套接字首先不是您的问题。你找错树了。
    【解决方案2】:

    这不是套接字引起的。您的应用程序的其他地方存在内存泄漏。您描述的行为最终会阻塞在 write() 方法中,并且不会消耗任何堆内存。

    【讨论】:

    • write() 不是阻塞调用。我有一个队列并从队列中读取,然后将其写入 socket.write()。根据石墨队列大小没有增长,这告诉我线程成功调用写入并从队列中删除该项目之后当服务器从缓冲区读取客户端泵数据时,堆大小是稳定的。
    • 你错了。 OutputStream.write() 一个阻塞调用,Writer.write() 也是。套接字写入进入套接字发送缓冲区,这是 (a) 固定大小和 (b) 在内核中,而不是 Java 堆。你的理论没有意义。尝试另一个。
    • 显然队列已满,由于写入阻塞,由于发送缓冲区已满,由于对等方未读取。我会完全摆脱队列并使用同步发送方法。
    • 队列用于批量记录,然后批量推送到google大查询。在同一个线程中,它现在将记录推送给订阅者。在每批之后,它会向石墨报告队列大小,因此我们确切地知道队列的大小。如果 write() 阻塞,则线程应该停止,但事实并非如此,数据继续跟随到 nosql。我相信我们遗漏了一些东西。我也可以在 UT 中看到这种行为。我可以抽取数百万个 GB 大小的记录,并且 write() 仍然可以,尽管服务器不处理数据并且内存正在消耗
    • 是的,你是对的。 write() 正在阻塞调用。我应该分拆另一个威胁,将批处理推送到 serversocket。
    猜你喜欢
    • 2012-03-29
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多