因此,我们可以扩展应用程序,添加新节点,删除节点,而无需考虑会话复制以及消耗的Java堆内存。
最近,我一直在从事高负载REST应用程序。 实际上,我们并不期望在那里有很高的流量,但是令人惊讶的是,我们已经为我们准备了更高的流量(这就是所谓的“快乐问题”)。 应用程序基于Spring框架 ,并通过部署在Apache Tomcat 7上的Spring Security进行保护。 所有资源都是完全无状态的–我的任何代码都没有触及HttpSession。 不幸的是,直到以下时间为止,用过的Java堆空间一直在增加:
java.lang.OutOfMemoryError: Java heap space
被扔了。 为了分析Java堆转储和堆的运行时使用情况,我使用了VisualVM 。
堆转储分析显示, Tomcat使用的ConcurrentHashMaps占用了很大一部分内存来存储会话。 这些会话对象几乎是空的,但是它们太多了,以至于它们消耗了约50%的保留Java堆空间。
向Tomcat启动脚本中添加参数: -XX:+HeapDumpOnOutOfMemoryError
以在java.lang.OutOfMemoryError: Java heap space
上获取Java堆转储
我要做的第一件事是将web.xml
会话超时从默认的30分钟限制为1分钟(可能的最低选择):
<?xml version='1.0' encoding='UTF-8'?>
<web-app xmlns='http://java.sun.com/xml/ns/javaee'xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'xsi:schemaLocation='http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd'version='3.0'><!-- ... --><session-config><session-timeout>1</session-timeout></session-config>
</web-app>
那解决了问题– GC清理了堆,结果更好,并且不再抛出OutOfMemoryError。 但是更重要的是这些会议来自何处? 答案是:Spring Security。
默认情况下,Spring Security根据需要创建会话-这意味着,如果用户已成功通过身份验证,则将创建会话。 就我而言,它意味着–总是如此。 为了防止Spring Security创建会话,需要将create-session='never'
添加到http
:
<http create-session='never'><!-- ... -->
</http>
您可能会认为–空的会话对象应该不是问题。 我可以告诉您,对于每秒处理数百个请求的应用程序来说,它确实是一个改变。 尤其是当它不在云中运行或只有很少的GB或RAM专用于Java堆时。 经过这些修改后,Java堆的用法如下所示:
参考:在软件开发之旅博客上,我们的JCG合作伙伴 Maciej Walkowiak 解决了REST + Spring Security会话问题 。
翻译自: https://www.javacodegeeks.com/2012/07/rest-spring-security-session-problem.html