【问题标题】:Performance problems when sending small files through Java Sockets通过 Java Sockets 发送小文件时的性能问题
【发布时间】:2015-03-12 05:08:17
【问题描述】:

我正在构建一个 Web 服务器应用程序,该应用程序使用 HTTP 1.1 协议和分块传输编码,根据请求将不同大小的文件从服务器发送到客户端。

我正在使用 Java Sockets/ServerSockets 来处理连接。我正在使用从socket.getOutputStream() 获得的输出流向客户端发送数据。注意:我没有将套接字的输出流包装在 BufferedOutputStream 中。

(我正在使用chrome调试器来分析资源时序)

我看到的问题是,一个大小为 1285 字节的文件(加上标头和块编码)需要 50 毫秒以上的时间让 chrome 接收请求的第一个字节。 (Chrome 报告的 TTFB 约为 50 毫秒),然后是传输的快速剩余部分(1-2 毫秒)(总传输时间约为 52 毫秒)

但是如果我将文件的大小增加到 1286 字节,TTFB 会显着降低到约 1 毫秒。 (总传输时间 ~3ms)

我尝试在沿途的不同点强制flushOutputStream,包括在请求标头之后、在块之后,甚至在每个点尝试多次flush 调用只是为了好玩。

我的问题:为什么与任何大于或等于 1286 字节的文件相比,小文件的传输时间要长这么多?我可以做些什么来解决这个性能问题?

我的理论:尽管 Java 调用了 flush(),但底层套接字实现中的某些东西忽略了对 flush 底层套接字缓冲区的 Java 请求。

【问题讨论】:

  • 这可能是因为你总是先测试小文件,然后测试大文件,它可能正在尝试建立连接,你可以换一种方式尝试(先发送大文件,然后发送小文件)稍后),看看你是否得到相同的结果?
  • 我刚刚更新了问题以澄清这是一个 Web 服务器类型的应用程序,因此文件是在不同时间请求的。 chrome 调试器将连接开销拆分为图表的一个单独部分,因此我看到的等待时间不包括任何一个文件的任何连接开销。
  • 我建议添加一个BufferedOutputStream,并删除除最后一个之外的所有刷新,重要的指标不是第一个字节的时间,而是最后一个字节的时间。
  • 我更新了问题以显示每个场景中的“总传输时间”。不幸的是,在混合中添加BufferedOutputStream 只会增加响应的额外延迟。因为在这种情况下,我既有本机套接字缓冲,也有 java 流缓冲。
  • 就代码而言,只有一个flush。其他东西只是为了测试。将尝试打开TCP_NODELAY

标签: java sockets


【解决方案1】:

【讨论】:

    猜你喜欢
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 2010-12-22
    • 2011-10-10
    • 2020-03-15
    • 1970-01-01
    相关资源
    最近更新 更多