Avoid duplicate flush when closing outputstream
Prior to this commit, the `HttpInvokerServiceExporter` would close its `ObjectOutputStream`, which itself issues duplicate flushes on the underlying `OutputStream`. Duplicate flushes can lead to multiple, separate TCP packets where those should be gathered writes. This commit wraps the underying stream with a decorator that guards against flush calls that are duplicated with the one done in `close`. Issue: SPR-14040
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.remoting.httpinvoker;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
@@ -169,7 +170,8 @@ public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExpor
|
||||
HttpServletRequest request, HttpServletResponse response, RemoteInvocationResult result, OutputStream os)
|
||||
throws IOException {
|
||||
|
||||
ObjectOutputStream oos = createObjectOutputStream(decorateOutputStream(request, response, os));
|
||||
ObjectOutputStream oos =
|
||||
createObjectOutputStream(new FlushGuardedOutputStream(decorateOutputStream(request, response, os)));
|
||||
try {
|
||||
doWriteRemoteInvocationResult(result, oos);
|
||||
}
|
||||
@@ -195,4 +197,25 @@ public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExpor
|
||||
return os;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorate an OutputStream to guard against {@code flush()} calls, which
|
||||
* are turned into no-ops.
|
||||
* <p>Because {@link ObjectOutputStream#close()} will in fact flush/drain
|
||||
* the underlying stream twice, this {@link FilterOutputStream} will
|
||||
* guard against individual flush calls. Multiple flush calls can lead
|
||||
* to performance issues, since writes aren't gathered as they should be.
|
||||
*
|
||||
* @see <a href="https://jira.spring.io/browse/SPR-14040">SPR-14040</a>
|
||||
*/
|
||||
class FlushGuardedOutputStream extends FilterOutputStream {
|
||||
public FlushGuardedOutputStream(OutputStream out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user