令人困惑的Tomcat持久会话内存配置文件 [英] Confusing Tomcat Persistent Session Memory Profile

查看:140
本文介绍了令人困惑的Tomcat持久会话内存配置文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与任何内存管理问题一样,这是一个很长的故事,所以请牢记于心.

As with any memory management issue, this is a long story, so strap-in.

我们的一个应用程序遇到了一些内存管理问题,因此我一直在尝试对该应用程序进行概要分析,以了解问题出在哪里.我今天早些时候看到了这个线程:

We have an application that has been suffering from some memory management issues, so I've been trying to profile the app to get an idea of where the problem lies. I saw this thread earlier today:

Tomcat会话逐出以避免OutOfMemoryError

...似乎跟我在探查器中看到的一样.基本上,如果我用Jmeter吸引了一群用户使用该应用程序,它将长时间保留在堆内存上,最终直到会话开始过期为止.但是,与该线程中的发布者不同,我拥有源代码,并且可以尝试使用Tomcat来实现持久状态会话,这是我今天一直在尝试的工作,但取得的成功有限.我认为这是我缺少的一些配置设置.这是我在context.xml中拥有的内容:

... which seems to follow suit with what I was seeing in the profiler. Basically, if I hit the app with a bunch of users with Jmeter it would hold onto the heap memory for a long time, eventually until the sessions began to expire. Unlike the poster in that thread however, I have the source, and the option to try to implement persistent state sessions with Tomcat, which is what I've been trying to do today, with limited success. I think it is some configuration setting I am missing. Here is what I have in context.xml:

  <Manager className='org.apache.catalina.session.PersistentManager'
                saveOnRestart='false'
                maxActiveSessions='5'
                minIdelSwap='0'
                maxIdleSwap='1'
                maxInactiveInterval='600'
                maxIdleBackup='0'>
   <Store className='org.apache.catalina.session.FileStore'/>
   </Manager>

在web.xml中,我有这个:

And in web.xml I have this:

<session-config>
    <session-timeout>
        10
    </session-timeout>
</session-config>

理想情况下,我希望会话在一个小时内超时,但是出于测试目的,这很好.现在,经过一番尝试之后,终于进入了这些设置,我正在探查器中查看该应用程序,这就是我所看到的:

Ideally I would like the sessions to timeout in an hour, but for testing purposes this is fine. Now after having played around with some things and finally coming to these settings, I am watching the app in the profiler and this is what I am seeing:

如您在图像中所见,我已经添加了一些注释.这是问号周围圈出的部分,我真的最了解不了.您可以看到我在几个不同的地方使用了Jconsole的"Perform GC"按钮,并且您可以看到图表中的部分,其中有很多使用Jmeter的客户在我的应用程序.

As you can see in the image, I have put some annotations. It's the part circled around the question mark which I really do not understand more than anything else. You can see that I am using the Jconsole 'Perform GC' button at a few different points, and you can see the part in the chart where I am hitting the application with many client with Jmeter.

如果我没记错(我必须回过头来并对其进行记录以确保确实),在实现持久状态之前,GC按钮在清除堆方面的作用不大.这里的奇怪之处在于,我似乎必须手动运行GC才能使此持久状态真正帮助任何事情.

If I recall correctly (I'd have to go back and really document it to be sure), before I implemented persistent state, the GC button would not do nearly as much with regards to clearing the heap. The strange bit here is that it seems like I have to manually run GC for this persistent state to actually help with anything.

或者,这仅仅是普通的内存泄漏情况吗?今天早些时候,我进行了一个堆转储,并将其加载到Eclipse Memory Analyzer工具中,并使用了检测泄漏"功能,并且所做的只是强化了一个理论,即这是一个会话大小的问题.它检测到的唯一泄漏是在java.util.concurrent.ConcurrentHashMap $ Segment中,这导致我进入此线程

Alternatively, is this just a plain memory leak scenario? Earlier today, I took a heap dump and loaded it into Eclipse Memory Analyzer tool, and used the 'Detect Leak' feature, and all it did was reinforce the theory that this is a session size issue; the only leak it detected was in java.util.concurrent.ConcurrentHashMap$Segment which led me to this thread Memory Fully utilized by Java ConcurrentHashMap (under Tomcat)

这让我认为实际上不是在泄漏应用程序.

which makes me think it's not the app that's actually leaking.

其他相关详细信息: -暂时在本机上运行/测试.这就是所有这些结果的来源. -使用Tomcat 6 -这是一个JSF2.0应用 -根据Tomcat文档,我添加了系统属性-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE = true

Other relevant details: - Running/testing this on my local machine for the time being. That's where all these results come from. - Using Tomcat 6 - This is a JSF2.0 app - I have added the system property -Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE=true as per the Tomcat documentation

所以,我想这里有几个问题: 1.我是否已正确配置? 2.是否存在内存泄漏? 3.该内存配置文件中发生了什么? 4.(相对)正常吗?

So, I guess there is several questions here: 1. Do I have this configured properly? 2. Is there a memory leak? 3. What is going on in this memory profile? 4. Is it (relatively) normal?

谢谢.

更新

因此,我尝试了Sean的技巧,并发现了一些有趣的新东西.

So, I tried Sean's tips, and found some new interesting things.

会话侦听器工作得很好,并且在分析此场景时起了重要作用.我忘了提到的另一件事是,应用程序的负载实际上仅由单个页面混淆,这几乎以可笑的比例达到了功能复杂性.因此,在测试中,有时我的目标是访问该页面,而其他时候我则避免访问该页面.因此,在下一轮测试中,这次使用会话侦听器,我发现了以下内容:

The session listener works great, and has been instrumental in analyzing this scenario. Something else, that I forgot to mention is that the app's load is only really confounded by a single page, which reaches a functional complexity on an almost comical proportion. So, in testing, I sometimes aim to hit that page, and other times I avoid it. So in my next round of tests, this time using the session listener I found the following:

1)只需访问一个简单页面,即可与几十个客户一起使用该应用程序.我注意到在指定的时间限制后所有会话均按预期方式释放,并且释放了内存.对于复杂的情况,点击大"页面,对于很少数量的客户来说,同样的事情就可以完美地发挥作用.

1) Hit the app with several dozen clients, just visiting a simple page. I noted that the sessions were all released as expected after the specified time limit, and the memory was released. Same thing works perfectly with a trivial number of clients, for the complex case, hitting the 'big' page.

2)接下来,我尝试使用具有数十个客户端的复杂用例来开发该应用程序.这次,发起了比预期更多的会话.似乎每个客户在一到三个会话之间启动.在会话到期时间之后,释放了一点内存,但是根据会话侦听器,只有大约三分之一的会话被破坏.与此相反,实际上包含会话数据的文件夹为空.大部分已使用的内存也被保留.但是,在运行压力测试一小时后,垃圾收集器开始运行,一切恢复正常.

2) Next, I tried hitting the app with the complex use case, with several dozen clients. This time, several dozen more sessions were initiated than expected. It seemed like every client initiated between one and three sessions. After the session expiration time, a little memory was released, but according to the session listener, only about a third of the sessions were destroyed. Contradicting that though, the folder which actually contains the sessions data is empty. Most of the memory that was used is being held, too. But, after exactly one hour of running the stress test, the garbage collector runs and everything is back to normal.

因此,后续问题包括:

1)为什么在简单的情况下可以正确处理会话,但是当事情占用大量内存时,它们就无法正确管理了?会话处理程序是否报告错误,还是使用JMeter会在某种程度上影响它?

1) Why might the sessions be handled properly in the simple case, but when things get memory intensive, they stop being managed correctly? Is the Session handler misreporting things, or does using JMeter impact this in some way?

2)为什么垃圾收集器要等待一小时才能运行?是否有系统设置要求垃圾收集器必须在给定的时间范围内运行,或者是否缺少某些配置设置?

2) Why does the garbage collector wait one hour to run? Is there a system setting that mandates that the garbage collector MUST run within a given time frame, or if there some configuration setting I'm missing?

再次感谢您的持续支持.

Thank you again for continued support.

更新2

简要说明一下:我进一步研究了这一点,发现我之所以获得有关实时会话数量的不同报告的原因是由于我使用的是持久会话;如果我关闭它,一切都会按预期进行.确实在Tomcat页面上表示持久会话,这是一项实验性功能.侦听器接听的肯定是呼叫会话事件,这是人们通常不希望这样做的事件.

Just a quick note: playing around with this some more, I found out the reason I was getting different reports about the number of live sessions is due to the fact that I am using persistent session; if I turn it off, everything works as expected. It indeed says on the Tomcat page for persistent session, that it is an experimental feature. It must be calling sessions events that the listener is picking up on, when one would atypically expect it to do so.

推荐答案

让我尽我所能来解决问题

Let me try and tackle the questions the best I can

  1. 对于您的配置,在纸面上对我来说看起来不错.如果要确保正确创建和销毁了会话,则需要设置会话侦听器以记录或显示打开的会话列表.这是示例

我认为没有内存泄漏.增量GC正在运行.似乎确实有很多记忆被提升为老一代.但是,一旦您的应用程序能够运行完整的GC,内存就会恢复正常.如果您需要在用户会话中存储大量数据,那么内存将是您的权衡.只要您注销/超时数据就销毁它们,从长远来看,内存应该没问题. 您的问题(???)区域将是您的会话仍处于活动状态的灰色区域,因此将保留其中存储的数据,这时可能会升级为旧一代.一旦内存升级为老一代,它需要一个完整的GC来清理它.单击该按钮即可.该应用程序最终将安排完整的GC.

I don't think there is a memory leak. The incremental GC's are being run. there does seems to be a lot of memory being promoted to the old gen. But once your application is able to run a full GC the memory is going back to normal. If you need your users session's to have a lot of data stored in them, memory will be your trade-off. As long as you destroy the data once they logout/timeout the memory should be ok in the long run. Your question (???) area would be the grey area where your sessions are still active so the data stored in them would be held, possibly promoted to the old gen at this point. Once memory is promoted to the Old Gen it needs a full GC to clean it up. Clicking the button did that. The application would have eventually scheduled the full GC.

我认为#2可以帮助回答这个问题

I think #2 helps answer this

确定压力测试看起来正常.尝试再次运行它,而不要单击Perform GC按钮.查看内存是否会自行下降.请注意,垃圾收集器会在认为应该执行完整GC时执行该操作.要清除旧版本,需要暂停,以便GC除非感觉不到没有足够的资源来正确管理应用程序,否则不会执行该操作.

Sure it looks normal for a stress test. Try running it again without hitting the Perform GC button. See if the memory will go back down by itself. Note that the garbage collector will do the full GC when it feels that it should do it. To clear the old gen requires pausing so the GC won't perform that action unless it feels it doesn't have enough resources to manage the application properly.

您可能需要做其他一些事情以进行将来的测试.注意堆的年轻代和老代之间的堆使用情况.从屏幕截图中我们可以看到有872mb的堆已提交,因此可以在负载测试期间对内存所在的位置进行分解,这将有助于正确确定堆的存放位置.

A few other things you may want to do for future tests. Take note of the heap usage between the young generation and the old generation of the heap. From the screenshot we can see there is 872mb of heap committed so to have a break down of where the memory is sitting during your load tests will help to identify properly where the heap is being kept.

以类似的方式考虑打开详细的GC 日志记录,以便您可以获取堆崩溃的报告.有很多工具可以帮助您绘制GC日志的图形,因此您不必手动读取日志.如果您不希望将其发送到stdout,也可以将其记录到文件(-Xloggc:file)中.

In similar fashion consider turning on verbose GC logging so you can get a report of the heap breakdown. there are many tools out there to help you graph the GC log so you don't have to read the log manually. This can also be logged to a file (-Xloggc:file) if you don't want it to be sent to stdout.

如果会话大小变得太大而无法管理,则可能需要将该内存转移到其他位置.一些示例可能是使用BigMemory,DB Persistance或其他减少会话大小的方法.

If the session size is becoming too large to manage, you may want to offload that memory elsewhere. A few examples may be to use BigMemory, DB Persistance, or some other way of reducing the session sizes.

这篇关于令人困惑的Tomcat持久会话内存配置文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆