gzip的详细配置请点击笔记:《tomcat的gzip压缩配置及优化效果对比》
提升Tomcat性能方法有很多种,使用NIO Connector和启用gzip压缩是其中两种。
NIO:Java New IO,使用了多路复用的技术,无疑要比普通的IO socket要高效。
gzip:对需要传输到前台的内容首先在内存中进行gzip压缩,这样可以大大的减少网络带宽占用。前提是前台的Accept-Encoding允许gzip。
但是,当同时配置了这两个时,会发现大于48KB的文件并没有进行压缩。
经查Tomcat源码,发现org.apache.catalina.servlets.DefaultServlet中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/**
* Check if sendfile can be used.
*/
protected
boolean
checkSendfile(HttpServletRequest request,
HttpServletResponse response,
CacheEntry entry,
long
length, Range range) {
if
((sendfileSize >
0
)
&& (entry.resource !=
null
)
&& ((length > sendfileSize) || (entry.resource.getContent() ==
null
))
&& (entry.attributes.getCanonicalPath() !=
null
)
&& (Boolean.TRUE == request.getAttribute(
"org.apache.tomcat.sendfile.support"
))
&& (request.getClass().getName().equals(
"org.apache.catalina.connector.RequestFacade"
))
&& (response.getClass().getName().equals(
"org.apache.catalina.connector.ResponseFacade"
))) {
request.setAttribute(
"org.apache.tomcat.sendfile.filename"
, entry.attributes.getCanonicalPath());
if
(range ==
null
) {
request.setAttribute(
"org.apache.tomcat.sendfile.start"
,
new
Long(0L));
request.setAttribute(
"org.apache.tomcat.sendfile.end"
,
new
Long(length));
}
else
{
request.setAttribute(
"org.apache.tomcat.sendfile.start"
,
new
Long(range.start));
request.setAttribute(
"org.apache.tomcat.sendfile.end"
,
new
Long(range.end +
1
));
}
return
true
;
}
else
{
return
false
;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
/**
* Serve the specified resource, optionally including the data content.
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
* @param content Should the content be included?
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet-specified error occurs
*/
protected
void
serveResource(HttpServletRequest request,
HttpServletResponse response,
boolean
content)
throws
IOException, ServletException {
......
// Copy the input stream to our output stream (if requested)
if
(content) {
try
{
response.setBufferSize(output);
}
catch
(IllegalStateException e) {
// Silent catch
}
if
(ostream !=
null
) {
if
(!checkSendfile(request, response, cacheEntry, contentLength,
null
))
copy(cacheEntry, renderResult, ostream);
}
else
{
copy(cacheEntry, renderResult, writer);
}
}
......
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/**
* Process pipelined HTTP requests using the specified input and output
* streams.
*
* @throws IOException error during an I/O operation
*/
public
SocketState process(NioChannel socket)
throws
IOException {
......
// Do sendfile as needed: add socket to sendfile and end
if
(sendfileData !=
null
&& !error) {
KeyAttachment ka = (KeyAttachment)socket.getAttachment(
false
);
ka.setSendfileData(sendfileData);
sendfileData.keepAlive = keepAlive;
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
//do the first write on this thread, might as well
openSocket = socket.getPoller().processSendfile(key,ka,
true
,
true
);
break
;
}
......
}
|
目前,尚不清楚使用NIO快,还是gzip较快,有待测试。
如果在使用NIO的同时还一定要用gzip,可以关闭NIO Connector的useSendFile选项。
1
2
3
4
5
6
7
8
|
connectionTimeout=
"20000"
redirectPort=
"8443"
useSendfile=
"false"
compression=
"on"
compressionMinSize=
"2048"
noCompressionUserAgents=
"gozilla, traviata"
compressableMimeType=
"text/html,text/xml,text/javascript"
/>
|