在处理过程中,发现有这么一个锁
"catalina-exec-6" daemon prio=10 tid=0xb7629400 nid=0x86a waiting for monitor entry [0x908e1000] java.lang.Thread.State: BLOCKED (on object monitor) at org.apache.tomcat.util.buf.StringCache.toString(StringCache.java:221) - waiting to lock <0x9c8adaf0> (a java.util.HashMap) at org.apache.tomcat.util.buf.ByteChunk.toString(ByteChunk.java:528) at org.apache.tomcat.util.buf.MessageBytes.toString(MessageBytes.java:196) at org.apache.catalina.connector.Request.getRequestURI(Request.java:2227) at org.apache.catalina.valves.AccessLogValve$RequestElement.addElement(AccessLogValve.java:1590) at org.apache.catalina.valves.AccessLogValve.log(AccessLogValve.java:962) at org.apache.catalina.core.AccessLogAdapter.log(AccessLogAdapter.java:51) at org.apache.catalina.core.ContainerBase.logAccess(ContainerBase.java:1263) at org.apache.catalina.core.ContainerBase.logAccess(ContainerBase.java:1270) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:441) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1879) - locked <0x9d178110> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701)
"catalina-exec-5" daemon prio=10 tid=0x91818800 nid=0x869 waiting for monitor entry [0x90932000] java.lang.Thread.State: BLOCKED (on object monitor) at org.apache.tomcat.util.buf.StringCache.toString(StringCache.java:221) - waiting to lock <0x9c8adaf0> (a java.util.HashMap) at org.apache.tomcat.util.buf.ByteChunk.toString(ByteChunk.java:528) at org.apache.tomcat.util.buf.MessageBytes.toString(MessageBytes.java:196) at org.apache.catalina.connector.Request.getRequestURI(Request.java:2227) at org.apache.catalina.valves.AccessLogValve$RequestElement.addElement(AccessLogValve.java:1590) at org.apache.catalina.valves.AccessLogValve.log(AccessLogValve.java:962) at org.apache.catalina.core.AccessLogAdapter.log(AccessLogAdapter.java:51) at org.apache.catalina.core.ContainerBase.logAccess(ContainerBase.java:1263) at org.apache.catalina.core.ContainerBase.logAccess(ContainerBase.java:1270) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:441) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1879) - locked <0x9cdabb90> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701)
"catalina-exec-2" daemon prio=10 tid=0x099ea000 nid=0x866 runnable [0x9129a000] java.lang.Thread.State: RUNNABLE at java.lang.String.equals(String.java:1025) at org.apache.tomcat.util.buf.StringCache$ByteEntry.equals(StringCache.java:657) at java.util.HashMap.get(HashMap.java:322) at org.apache.tomcat.util.buf.StringCache.toString(StringCache.java:293) - locked <0x9c8adaf0> (a java.util.HashMap) at org.apache.tomcat.util.buf.ByteChunk.toString(ByteChunk.java:528) at org.apache.tomcat.util.buf.MessageBytes.toString(MessageBytes.java:196) at org.apache.catalina.connector.Request.getRequestURI(Request.java:2227) at org.apache.catalina.valves.AccessLogValve$RequestElement.addElement(AccessLogValve.java:1590) at org.apache.catalina.valves.AccessLogValve.log(AccessLogValve.java:962) at org.apache.catalina.core.AccessLogAdapter.log(AccessLogAdapter.java:51) at org.apache.catalina.core.ContainerBase.logAccess(ContainerBase.java:1263) at org.apache.catalina.core.ContainerBase.logAccess(ContainerBase.java:1270) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:441) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1879) - locked <0x9d0e9a10> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701)
"catalina-exec-1" daemon prio=10 tid=0x9180fc00 nid=0x865 waiting for monitor entry [0x910ab000] java.lang.Thread.State: BLOCKED (on object monitor) at org.apache.tomcat.util.buf.StringCache.toString(StringCache.java:221) - waiting to lock <0x9c8adaf0> (a java.util.HashMap) at org.apache.tomcat.util.buf.ByteChunk.toString(ByteChunk.java:528) at org.apache.tomcat.util.buf.MessageBytes.toString(MessageBytes.java:196) at org.apache.catalina.connector.Request.getRequestURI(Request.java:2227) at org.apache.catalina.valves.AccessLogValve$RequestElement.addElement(AccessLogValve.java:1590) at org.apache.catalina.valves.AccessLogValve.log(AccessLogValve.java:962) at org.apache.catalina.core.AccessLogAdapter.log(AccessLogAdapter.java:51) at org.apache.catalina.core.ContainerBase.logAccess(ContainerBase.java:1263) at org.apache.catalina.core.ContainerBase.logAccess(ContainerBase.java:1270) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:441) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1879) - locked <0x9ce8d5c0> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701) |
这里是为了记录access日志
修改方法:
修改org.apache.tomcat.util.buf.ByteChunk类
// -------------------- Conversion and getters --------------------
@Override public String toString() { if (null == buff) { return null; } else if (end-start == 0) { return ""; } return StringCache.toString(this); } |
修改为
// -------------------- Conversion and getters --------------------
@Override public String toString() { if (null == buff) { return null; } else if (end-start == 0) { return ""; } //return StringCache.toString(this); StringCache.accessCount++; return this.toStringInternal(); } |
这里忽略了StringCache的accessCount和hitCount两个统计字段。
在调试时,发现有个锁
"catalina-exec-159" daemon prio=10 tid=0x91842c00 nid=0xd30 waiting for monitor entry [0x90473000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:353)
- waiting to lock <0x9d027848> (a org.apache.jasper.servlet.JspServletWrapper)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1879)
- locked <0x9db454c0> (a org.apache.tomcat.util.net.NioChannel)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:701)
查看源码找到位置所在:
/*
* (1) Compile
*/
if (options.getDevelopment() || firstTime ) {
synchronized (this) {
firstTime = false;
// The following sets reload to true, if necessary
ctxt.compile();
}
} else {
if (compileException != null) {
// Throw cached compilation exception
throw compileException;
}
}
说明如果是开发模式或者第一次加载时,都需要执行此同步块。
通过打印日志
可以看到,基本上除了因为第一次加载外,其它全部是因为处于开发模式而导致重新进入此模块。
那么如何让Tomcat运行在非Develop模式?
见org.apache.jasper.EmbeddedServletOptions的565行。
看来可以在配置文件中配置。
在对应的servelt的配置项中
<init-param>
<param-name>development</param-name>
<param-value>false</param-value>
</init-param>
修改后的效果如下:
也可以直接修改代码,将development字段的默认值设置为false.
在AccessLogValve.java的1144行。代码为
synchronized (this) {
if (writer != null) {
writer.println(message);
if (!buffered) {
writer.flush();
}
}
}
如果不需要access log记录,则可以屏蔽掉这段代码。
这个根据实际的需要决定。
通过查看线程栈jstack,可以看到
"catalina-exec-6" daemon prio=10 tid=0x90705400 nid=0x4ab waiting for monitor entry [0x906ad000] java.lang.Thread.State: BLOCKED (on object monitor) at java.io.PrintWriter.write(PrintWriter.java:427) - waiting to lock <0x9c551ec8> (a java.io.OutputStreamWriter) at java.io.PrintWriter.write(PrintWriter.java:446) at org.apache.juli.FileHandler.publish(FileHandler.java:208) at java.util.logging.Logger.log(Logger.java:573) at java.util.logging.Logger.doLog(Logger.java:598) at java.util.logging.Logger.logp(Logger.java:714) at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:183) at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:146) at org.apache.tomcat.util.net.NioEndpoint$Poller.addEvent(NioEndpoint.java:1043) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1081) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1072) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.release(Http11NioProtocol.java:221) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:616) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1876) - locked <0x9cdf2ed8> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701)
"catalina-exec-5" daemon prio=10 tid=0x9172ec00 nid=0x4aa runnable [0x906fe000] java.lang.Thread.State: RUNNABLE at java.io.FileOutputStream.writeBytes(Native Method) at java.io.FileOutputStream.write(FileOutputStream.java:300) at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:220) at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:290) at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:294) at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:140) - locked <0x9c551ec8> (a java.io.OutputStreamWriter) at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229) at java.io.PrintWriter.flush(PrintWriter.java:293) - locked <0x9c551ec8> (a java.io.OutputStreamWriter) at org.apache.juli.FileHandler.publish(FileHandler.java:210) at java.util.logging.Logger.log(Logger.java:573) at java.util.logging.Logger.doLog(Logger.java:598) at java.util.logging.Logger.logp(Logger.java:714) at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:183) at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:146) at org.apache.tomcat.util.net.NioEndpoint$Poller.addEvent(NioEndpoint.java:1043) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1081) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1072) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.release(Http11NioProtocol.java:221) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:616) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1876) - locked <0x92350190> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701)
"catalina-exec-4" daemon prio=10 tid=0x90700800 nid=0x4a9 waiting for monitor entry [0x90883000] java.lang.Thread.State: BLOCKED (on object monitor) at java.io.PrintWriter.write(PrintWriter.java:427) - waiting to lock <0x9c551ec8> (a java.io.OutputStreamWriter) at java.io.PrintWriter.write(PrintWriter.java:446) at org.apache.juli.FileHandler.publish(FileHandler.java:208) at java.util.logging.Logger.log(Logger.java:573) at java.util.logging.Logger.doLog(Logger.java:598) at java.util.logging.Logger.logp(Logger.java:714) at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:183) at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:146) at org.apache.tomcat.util.net.NioEndpoint$Poller.addEvent(NioEndpoint.java:1043) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1081) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1072) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.release(Http11NioProtocol.java:221) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:616) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1876) - locked <0x9ce324f0> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701)
"catalina-exec-3" daemon prio=10 tid=0x91711800 nid=0x4a8 waiting for monitor entry [0x908d4000] java.lang.Thread.State: BLOCKED (on object monitor) at java.io.PrintWriter.write(PrintWriter.java:427) - waiting to lock <0x9c551ec8> (a java.io.OutputStreamWriter) at java.io.PrintWriter.write(PrintWriter.java:446) at org.apache.juli.FileHandler.publish(FileHandler.java:208) at java.util.logging.Logger.log(Logger.java:573) at java.util.logging.Logger.doLog(Logger.java:598) at java.util.logging.Logger.logp(Logger.java:714) at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:183) at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:146) at org.apache.tomcat.util.net.NioEndpoint$Poller.addEvent(NioEndpoint.java:1043) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1081) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1072) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.release(Http11NioProtocol.java:221) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:616) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1876) - locked <0x9cc577a0> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701)
"catalina-exec-2" daemon prio=10 tid=0x911df000 nid=0x4a7 waiting for monitor entry [0x90925000] java.lang.Thread.State: BLOCKED (on object monitor) at java.io.PrintWriter.write(PrintWriter.java:427) - waiting to lock <0x9c551ec8> (a java.io.OutputStreamWriter) at java.io.PrintWriter.write(PrintWriter.java:446) at org.apache.juli.FileHandler.publish(FileHandler.java:208) at java.util.logging.Logger.log(Logger.java:573) at java.util.logging.Logger.doLog(Logger.java:598) at java.util.logging.Logger.logp(Logger.java:714) at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:183) at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:146) at org.apache.tomcat.util.net.NioEndpoint$Poller.addEvent(NioEndpoint.java:1043) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1081) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1072) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.release(Http11NioProtocol.java:221) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:616) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1876) - locked <0x9ce18148> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701)
"catalina-exec-1" daemon prio=10 tid=0x093c7800 nid=0x4a6 waiting for monitor entry [0x90f5c000] java.lang.Thread.State: BLOCKED (on object monitor) at java.io.PrintWriter.write(PrintWriter.java:427) - waiting to lock <0x9c551ec8> (a java.io.OutputStreamWriter) at java.io.PrintWriter.write(PrintWriter.java:446) at org.apache.juli.FileHandler.publish(FileHandler.java:208) at java.util.logging.Logger.log(Logger.java:573) at java.util.logging.Logger.doLog(Logger.java:598) at java.util.logging.Logger.logp(Logger.java:714) at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:183) at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:146) at org.apache.tomcat.util.net.NioEndpoint$Poller.addEvent(NioEndpoint.java:1040) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1081) at org.apache.tomcat.util.net.NioEndpoint$Poller.add(NioEndpoint.java:1072) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.release(Http11NioProtocol.java:221) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:616) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1876) - locked <0x9cd925b8> (a org.apache.tomcat.util.net.NioChannel) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:701) |
可见默认的日志logger效率比较低,因为写文件是互斥锁。
查看at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:146)
此处可以修改源码为更高效的日志组件。
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
compression="on"
compressionMinSize="2048"
/>
可以使得返回给client的数据量减少。
1 http://www.tuicool.com/articles/vU7bya3
2 http://itindex.net/detail/50701-tomcat-bio-nio.apr
3 http://www.365mini.com/page/tomcat-connector-mode.htm
4 http://www.oschina.net/question/54100_16195
5 http://blog.itpub.net/29510932/viewspace-1102187/