Memory 使用大量内存的SpringWebFlow
我们的Webflow(2.3.1)应用程序要求为我们通过浏览器打开的每个新流占用大量内存 下面的屏幕截图显示了应用程序的内存使用情况。当应用程序启动时,最初需要400 Mb。之后,我们在浏览器中打开4个单独的、相同的Webflow测试页面,每个页面占用约90Mb的额外内存 每个测试页都从其自己的简单流定义开始:Memory 使用大量内存的SpringWebFlow,memory,out-of-memory,spring-webflow,Memory,Out Of Memory,Spring Webflow,我们的Webflow(2.3.1)应用程序要求为我们通过浏览器打开的每个新流占用大量内存 下面的屏幕截图显示了应用程序的内存使用情况。当应用程序启动时,最初需要400 Mb。之后,我们在浏览器中打开4个单独的、相同的Webflow测试页面,每个页面占用约90Mb的额外内存 每个测试页都从其自己的简单流定义开始: <?xml version="1.0" encoding="UTF-8"?> <flow xmlns:xsi="http://www.w3.org/2001/XMLS
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/webflow"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd" start-state="start">
<view-state id="start" view="test/test1">
</view-state>
<end-state id="end"/>
<bean-import resource="../flow-beans.xml"/>
</flow>
JSP测试页面也非常简单,只有一行文本是空的
当前,当我们将JVM内存设置为1.5Gb时,在打开大约15个不同的流之后,应用程序最终在服务器上崩溃,并出现OutOfMemoryException。考虑到我们屏幕的低复杂性,1.5 Gb似乎有点多
我们想知道Webflow声称的这些简单流/页的内存量是否是预期的,因此我们是否应该为服务器JVM分配更多内存。如果没有,我们想知道如何减少这种内存使用
下面是我们的整个webflow配置
我们尝试添加一个flow execution repository标记,并使用max executions快照和max executions值,但即使是最保守的设置也不会改变我们看到的内存使用情况
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Launches new flow executions and resumes existing executions. -->
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
</webflow:flow-executor>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:our.properties" />
<property name="placeholderPrefix" value="$xxxx"></property>
</bean>
<tx:annotation-driven transaction-manager="$xxxx{txManager}" />
<!-- Creates the registry of flow definitions for this application -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location-pattern value="classpath:flows/**/*-flow.xml" />
</webflow:flow-registry>
<bean id="viewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="viewResolver" />
</bean>
<bean id="expressionParser" class="org.springframework.expression.spel.standard.SpelExpressionParser">
<constructor-arg name="configuration">
<bean class="org.springframework.expression.spel.SpelParserConfiguration">
<constructor-arg name="autoGrowCollections" value="true" />
<constructor-arg name="autoGrowNullReferences" value="false" />
</bean>
</constructor-arg>
</bean>
<bean id="webflowExpressionParser" class="org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser">
<constructor-arg name="expressionParser" ref="expressionParser" />
</bean>
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="viewFactoryCreator" validator="validator" expression-parser="webflowExpressionParser"/>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="projectVersion" class="our.company.versions.ProjectVersionUtil">
<property name="xxxxVersion" value="$xxxx{xxxx.version}" />
<property name="systemConfigurationDao">
<ref bean="SystemConfigurationDao"/>
</property>
</bean>
</beans>
当SpringWebFlow启动一个新的流时,它基本上构建一个新的
BeanFactory
,加载xml文件并导入任何其他xml文件。新建的BeanFactory
将DispatcherServlet
的上下文作为其父级
现在的问题是,bean工厂构造了所有bean的实例,甚至是在导入的XML文件中定义的实例
<bean-import resource="../flow-beans.xml"/>
如果其中有很多bean,那么每个流实例都会复制这些bean。通常,您不希望所有bean都被复制并存储在用户会话中
从
flowbean.xml
中删除单例bean,并将它们放在正常的应用程序上下文中,它们仍然可以从流定义中引用。或者,您可以简单地将flowbeans.xml
添加到应用程序启动时加载的文件列表中。我怀疑您基本上是在每次需要时重新加载Singleton。我怀疑您的流bean.xml
中包含的bean应该是应用程序单例,但会为每个流实例重新加载。我只是在一个绑定器的构造函数中放置了一个断点,它会与我们访问的每个新流一起命中,所以看起来您是对的。我将对此进行进一步的调查,稍后还会提供更多信息。非常感谢。另外,展示如何配置web.xml和*-flow xmls。@M.Deinum:我们现在从web.xml加载flow-beans.xml作为一个普通的应用程序上下文,并且我们已经从流定义中删除了所有bean导入标记。结果:内存使用减少60-70%。你能把你的答案复制成一个新的答案吗?然后我把它标为答案。再次感谢。