【问题标题】:Java: IOUtils.toByteArray(input) taking too long for some requests causing high TP99.9Java:IOUtils.toByteArray(input) 对某些请求花费太长时间导致高 TP99.9
【发布时间】:2020-08-21 11:58:39
【问题描述】:

我正在使用以下代码 sn-p 记录我的请求。大多数情况下,我的请求都在 100 毫秒内送达。但是,有时读取缓冲区的时间过长,导致 TP99.9 较高。

final HttpServletRequest rq = (HttpServletRequest) request;
final BufferedReqWrapper brq = new BufferedReqWrapper(rq);

然后在 BufferedReqWrapper 中

private final BufferingIPStream bis;


public BufferedReqWrapper(final HttpServletRequest req, final Integer maxBytesToBuffer) throws IOException
    {
        super(req);
        bis = new BufferingIPStream(super.getInputStream());
    }

在缓冲IP流中

public BufferingIPStream(final InputStream delegate) throws IOException
    {
        this.delegate = delegate;
        buffer = fillBuffer(delegate);
    }

而fillbuffer方法是

private byte[] fillBuffer(final InputStream input) throws IOException
{
    return IOUtils.toByteArray(input);
}

此代码适用于大多数请求,但有时会花费很长时间,这会导致超过 1000 毫秒的高延迟(TP99.9 变高)。

【问题讨论】:

    标签: java arrays buffer inputstream bufferedreader


    【解决方案1】:

    这是预期的,因为InputStream 读取是阻塞的,这意味着当您调用read 时,该方法将阻塞(等待数据可用)。 IOUtils.toByteArray 会以某种方式依赖流的read 方法。

    【讨论】:

    • 有没有其他方法可以快速将 InputStream 转换为 Byte 数组?
    • 不是真的没有,如果数据不可用,那么没有办法更快地读取它。
    • 为什么当我捕获请求并将其作为参数final HttpServletRequest rq = (HttpServletRequest) request; 发送时数据不存在?当我捕获请求时,我们会在此变量中看到数据。是和机器容量还是资源有关?
    • HttpServletRequest 不包含数据。数据来自您使用HttpServletRequest 对象打开的流。流从远程客户端读取数据。
    【解决方案2】:

    这有很多可能的原因:

    1. 客户端(例如浏览器)可能位于慢速机器或慢速网络上。 IOUtils.toByteArray ... 或者其他任何东西 ... 只能从远程系统读取数据,速度与数据通过网络传输的速度一样快。

    2. 有些请求可能很大;即比典型的大得多。较大的请求将需要更长的时间才能读入byte[]

    3. 您可能会看到 GC 暂停。如果 GC 调整非常适合您的工作负载,那么长时间的 GC 暂停应该很少见。但是,特定的请求模式可能会导致 GC 暂停足够长的时间,从而导致请求时间过长。

    值得注意的是,将大型请求读入byte[] 将需要大量内存分配,最大的内存分配高达请求大小的 2 倍。大内存分配更有可能导致(更昂贵的)老年代收集。在最坏的情况下,过大的垃圾回收会触发“完整”垃圾回收,这(取决于 GC 选择和调整)会导致严重的暂停。

    最后,您不应该忽视这样的可能性,即长请求时间实际上是由于您的 web 应用程序中发生的其他事情......或另一个进程......或与您相同的管理程序上的另一个虚拟服务器。

    我会建议:

    • 记录请求大小以查看它们是否与慢速请求相关
    • 记录客户端 IP 并查找相关性
    • 打开 GC 日志并查找相关性
    • 如果您有系统负载图(CPU、磁盘 I/O、网络 I/O),请查找相关性

    利用您的观察来尝试找出问题可能是什么。 (在没有任何证据的情况下猜测原因绝不是一个好主意......)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      • 2021-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 1970-01-01
      相关资源
      最近更新 更多