Sun Web Server 7 服务 .jsp - Eden 空间行为 - 可能存在内存泄漏

发布于 2024-11-27 18:19:56 字数 2507 浏览 0 评论 0原文

我的公司最近迁移到 Alfresco 作为内容管理解决方案。由于某些内容是动态的(包含在另一个 .jsp 中的 .jsp 文件读取从 Alfresco 发布为 xml 的站点地图 并将结果缓存 24 小时)生成的文件为 .jsp,并通过我们的 Sun Web Server 7 servlet 容器进行 rsync 和服务。

每个页面都有一个页眉、一个菜单和一个页脚 使用 jsp:include 运行时指令。我的理解是,当第一次请求index.jsp时,会有许多编译好的jsp,例如index.classheader.class >, menu.classfooter.class。要求是让这些文件编译一次,servlet 容器每 x 秒检查任何源 jsps(由 Alfresco 推出)的修改。

Web 服务器本身已配置 (default-web.xml),可按照 Sun 文档的建议使用以下参数进行生产:

<init-param>
  <param-name>development</param-name>
  <param-value>false</param-value>
</init-param>
<init-param>
  <param-name>checkInterval</param-name>
  <param-value>0</param-value>
</init-param>   
  <init-param>
  <param-name>fork</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
  <param-name>mappedfile</param-name>
  <param-value>false</param-value>
</init-param>
<init-param>
  <param-name>suppressSmap</param-name>
  <param-value>true</param-value>
</init-param>
<init-param>
  <param-name>classdebuginfo</param-name>
  <param-value>false</param-value>
</init-param>
<init-param>
  <param-name>trimSpaces</param-name>
  <param-value>true</param-value>
</init-param>

请注意,checkInterval 参数应为设置为 60,但是这样做会导致 Web 服务器无法启动(我一直无法弄清楚为什么)。不幸的解决方法是 然后将 development 设置为 true,这是我想避免的。

servlet 容器使用以下 JVM 设置进行配置(再次按照 Sun 文档的建议):

-server -Xrs -Xmx2048m -Xms2048m -Xmn2024m -XX:+AggressiveHeap -XX:LargePageSizeInBytes=256m -XX:+UseParallelOldGC -XX:+UseParallelGC -XX:ParallelGCThreads=8 -XX:+DisableExplicitGC

在性能测试期间,我们看到 Eden 空间频繁达到 2GB(静态内容的总大小大约为 200mb,我们的静态内容的总大小约为 200mb)。 测试是针对少数页面进行的)。结果产生了许多小型收藏;将对象快速推入 Tenured 空间,并且它永远不会真正恢复,导致大量频繁的 Full GC (幸存者空间也从 90mb 缩小到 2 字节,我只能假设是伊甸园空间声称它是自己的 - 谁能确认?)。这是我们最大的问号;我们的开发人员都没有 认为这是正常行为,但我们无法解释记忆的去向。

负载下 Eden 空间的快照

我们看到的另一个问题是线程计数。每个 http 请求都会在 servlet 中产生一个新线程,我希望它与负载成比例地增加(我也认为创建了一个新线程 在运行时执行 jsp:include 时,也在每个 servlet 中(编译的父 jsp 中的 RequestDispatcher.include())。然而,一旦每个请求得到服务,线程就会死亡,并在其位置生成一个新线程。 这是一个正确的假设吗?无论负载如何,线程计数似乎都会停止并增长。

任何帮助将不胜感激。

My company has recently moved to Alfresco as a content management solution. As some of the content is dynamic (a .jsp file that is included in another .jsp reads a sitemap published as xml from Alfresco
and caches the result for 24hr) the generated files are of .jsp and are rsync'ed and served from our Sun Web Server 7 servlet container.

Each page has a header, a menu, and a footer that is included
using the jsp:include runtime directive. My understanding is that when the first request is made to index.jsp there will be a number of compiled jsps e.g. index.class, header.class,
menu.class, and footer.class. The requirement is to have these compile once with the servlet container checking for modification of any of the source jsps (pushed out by Alfresco) every x seconds.

The web server itself has been configred (default-web.xml) to be production-ready with the following parameters as recommended by Sun docs:

<init-param>
  <param-name>development</param-name>
  <param-value>false</param-value>
</init-param>
<init-param>
  <param-name>checkInterval</param-name>
  <param-value>0</param-value>
</init-param>   
  <init-param>
  <param-name>fork</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
  <param-name>mappedfile</param-name>
  <param-value>false</param-value>
</init-param>
<init-param>
  <param-name>suppressSmap</param-name>
  <param-value>true</param-value>
</init-param>
<init-param>
  <param-name>classdebuginfo</param-name>
  <param-value>false</param-value>
</init-param>
<init-param>
  <param-name>trimSpaces</param-name>
  <param-value>true</param-value>
</init-param>

Note that the checkInterval parameter should be set to 60, but doing this results in the web server failing to start (I haven't been able to figure out why). The unfortunate workaround for this is
then to set development to true, which I'd like to avoid.

The servlet container is configured with the following JVM settings (again as recommended by Sun docs):

-server -Xrs -Xmx2048m -Xms2048m -Xmn2024m -XX:+AggressiveHeap -XX:LargePageSizeInBytes=256m -XX:+UseParallelOldGC -XX:+UseParallelGC -XX:ParallelGCThreads=8 -XX:+DisableExplicitGC

During performance testing we are seeing the Eden space spiking frequently to 2gb (The total size of our static content is roughly 200mb, and our
testing is against a handful of pages). The results in alot of minor collections; pushing objects quickly into Tenured space, and it never really recovers resulting in alot of frequent full GC
(The survivor space also shrinks from 90mb to 2 bytes which I can only assume is Eden space claiming it for its own - can anyone confirm?). This is our biggest questionmark; none of our developers
think this is normal behaviour, but we cannot explain where that memory is going.

Snapshot of Eden space under load

The other issue we are seeing is thread count. With each http request resulting in a new thread at the servlet, I would expect it to rise proportional to the load (I also think a new thread is created
within each servlet too when doing a jsp:include at runtime (RequestDispatcher.include() in the compiled parent jsp). However, once each request is serviced the thread should die and a new one spawned in its place.
Is this a correct assumption? The thread count seems to stop and grow irrespective of the load.

Any help would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

对风讲故事 2024-12-04 18:19:56

堆使用图中的锯齿模式是正常的,并不表示存在内存泄漏。仅当锯齿波的下限随着时间的推移呈上升趋势时,才表明存在内存泄漏。

然而,始终执行 Full GC 是一个问题,这可能表明存在存储泄漏。尝试使用内存分析器运行,看看是否可以发现泄漏的内容。

我有一种感觉,我知道可能是什么导致了泄漏。我认为您说过您正在动态生成 JSP。每次容器找到新的(或更新的)JSP 时,它都会生成 Java 类,编译这些类,然后加载字节码。如果您不小心,旧类/旧版本的类将保持可达性并发生泄漏。


我也不希望线程数随着负载而上升和下降。一个像样的 Web 容器将维护一个用于处理传入请求的线程池。线程池通常有一个固定的上限,这样请求风暴不会导致线程数量爆炸,从而导致资源使用和争用问题。

A sawtooth pattern in the heap usage graph is normal, and not indicative of the memory leak. A memory leak is only indicated if the lower bound of the sawtooth trends upwards over time.

However, always performing Full GCs is a concern, and this may indicate a storage leak. Try running with a memory profiler to see if you can spot what is leaking.

I have a feeling that I know what might be causing the leak. I think you said that you are dynamically generating JSPs. Each time the container finds a new (or updated) JSP, it generates Java classes, compiles the classes and then loads the bytecodes. If you are not careful, the old classes / old versions of classes will remain reachable and leak.


I would also not expect the thread count to rise and fall with the load. A decent web container will maintain a pool of threads that are used to process incoming requests. The thread pool typically has a fixed upper bound so that a storm of requests doesn't lead to an explosion of the number of threads, resulting in resource usage and contention problems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文