浏览 4010 次
锁定老帖子 主题:Tomcat异步Servlet占用内存问题
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-06-11
最后修改:2012-06-11
Author:xiaohanghu Date: 2012/6/11 Email:huhang1986@gmail.com
进行auto-comet(http://code.google.com/p/auto-comet/)连接数测试的时候,发现Tomcat7内存增长飞快,3000个连接的时候占用了250MB内存,导致堆溢出。
于是编写了一个测试类,查找Tomcat占用内存的问题:
import java.io.IOException; import java.io.Serializable; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.AsyncContext; //import org.apache.catalina.connector.Request; import org.apache.catalina.connector.InputBuffer; import org.apache.catalina.connector.Request; import org.apache.catalina.core.AsyncContextImpl; import org.auto.comet.ConcurrentPushSocket; import org.auto.comet.PushSocket; /** * org.apache.catalina.connector.Request * 对象占用内存非常多,导致comet连接占用内存非常多(平均一个连接占用内存8KB+) * * @author xiaohanghu */ public class MemoryTest { private static final MemoryMXBean memoryMXBean = ManagementFactory .getMemoryMXBean(); protected static Map<Serializable, Object> socketStore = new ConcurrentHashMap<Serializable, Object>(); // protected static Map<Serializable, PushSocket> socketStore = // Collections.EMPTY_MAP; public static void main(String[] args) throws IOException { for (int i = 0; i < 8000; i++) { // Request request = new Request(); // socketStore.put("asdfsdfsadf" + i, new ConcurrentPushSocket()); // AsyncContext asyncContext = new AsyncContextImpl(request); // socketStore.put("asdfsdfsadfa" + i, asyncContext); // socketStore.put("asdfsdfsadfa" + i, request);// 占内存非常多 // request.finishRequest(); InputBuffer inputBuffer = new InputBuffer(); socketStore.put("asdfsdfsadfa" + i, new InputBuffer());// 罪魁祸首 inputBuffer.close(); } MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage(); long usedBytes = memoryUsage.getUsed(); System.out.println("used :" + usedBytes / 1024 / 1024 + " MB"); } }
原来罪魁祸首是org.apache.catalina.connector.Request类的一个实例变量InputBuffer导致的:
/** * The associated input buffer. */ protected InputBuffer inputBuffer = new InputBuffer();
而org.apache.catalina.connector.InputBuffer的默认大小是8*1024!也就是说每个Request对象占用内存大于8KB。而在异步的AsyncContext对象没有回收前,这8KB的内存也无法回收!在request读取完毕后,InputBuffer对象就已经没有用了,这个算得上是Tomcat7的严重的内存问题了! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-06-12
那么去tomcat的邮件列表里面反应一下吧。和他们讨论一下这个问题。
|
|
返回顶楼 | |
发表时间:2012-06-12
已经提交到他们的BUG列表了。
|
|
返回顶楼 | |
发表时间:2012-06-13
Tomcat的开发人员,回复无法修复,这个跟他们的整体设计有关:
https://issues.apache.org/bugzilla/show_bug.cgi?id=53401 The InputBuffer may not be necessary in your use case, but it is required in the general case both for performance and for pipe-lining. WebSocket can and does use lighter weight objects and should be much more scalable. |
|
返回顶楼 | |