Java:IOUtils.toByteArray(input)对于某些导致TP99.9高的请求花费的时间太长

问题描述 投票:0回答:2

我在记录我的请求时使用了以下代码段。我大部分时间是在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());
    }

在BufferingIPStream中

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
2个回答
1
投票

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


0
投票

有许多可能的原因:

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

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

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

值得注意的是,将大请求读入byte[]将需要一定数量的内存分配,最大的内存分配最多可达请求大小的2倍。较大的内存分配更有可能导致(更昂贵的)旧版本集合。在最坏的情况下,过大的收集会触发“完整”垃圾收集,这(取决于GC选择和调整)会导致明显的暂停。

最后,您不应低估这种漫长的请求时间实际上是由于您的Web应用程序...,其他进程...或与您的虚拟机管理程序位于同一虚拟机管理程序上的其他虚拟服务器引起的。

© www.soinside.com 2019 - 2024. All rights reserved.