我正在调查 Jetty 6.1.26 的性能问题。 Jetty 似乎使用Transfer-Encoding: chunked
,并且根据所使用的缓冲区大小,本地传输时可能会非常慢。
我创建了一个小型 Jetty 测试应用程序,其中包含一个演示该问题的 servlet。
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.servlet.Context;
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
final int bufferSize = 65536;
resp.setBufferSize(bufferSize);
OutputStream outStream = resp.getOutputStream();
FileInputStream stream = null;
try {
stream = new FileInputStream(new File("test.data"));
int bytesRead;
byte[] buffer = new byte[bufferSize];
while( (bytesRead = stream.read(buffer, 0, bufferSize)) > 0 ) {
outStream.write(buffer, 0, bytesRead);
outStream.flush();
}
} finally {
if( stream != null )
stream.close();
outStream.close();
}
}
public static void main(String[] args) throws Exception {
Server server = new Server();
SelectChannelConnector ret = new SelectChannelConnector();
ret.setLowResourceMaxIdleTime(10000);
ret.setAcceptQueueSize(128);
ret.setResolveNames(false);
ret.setUseDirectBuffers(false);
ret.setHost("0.0.0.0");
ret.setPort(8080);
server.addConnector(ret);
Context context = new Context();
context.setDisplayName("WebAppsContext");
context.setContextPath("/");
server.addHandler(context);
context.addServlet(TestServlet.class, "/test");
server.start();
}
}
在我的实验中,我使用 servlet 返回给客户端的 128MB 测试文件,客户端使用 localhost 进行连接。使用用 Java 编写的简单测试客户端下载此数据(使用URLConnection
)需要 3.8 秒,这非常慢(是的,它是 33MB/s,这听起来并不慢,除了这纯粹是本地的并且输入文件被缓存;它应该快得多)。
现在事情变得奇怪了。如果我使用 wget 下载数据,它是一个 HTTP/1.0 客户端,因此不支持分块传输编码,只需要 0.1 秒。这是一个更好的数字。
现在当我改变时bufferSize
到4096,Java客户端需要0.3秒。
如果我删除对resp.setBufferSize
完全(似乎使用 24KB 块大小),Java 客户端现在需要 7.1 秒,并且 wget 突然同样慢!
请注意,我绝不是 Jetty 方面的专家。我在使用reduce任务洗牌诊断Hadoop 0.20.203.0中的性能问题时偶然发现了这个问题,它使用Jetty以类似于缩减示例代码的方式传输文件,缓冲区大小为64KB。
该问题在我们的 Linux (Debian) 服务器和我的 Windows 机器上以及 Java 1.6 和 1.7 上都会重现,因此它似乎完全依赖于 Jetty。
有谁知道可能导致此问题的原因是什么,以及我是否可以对此做些什么?