【问题标题】:Extremelly high CPU usage in JSF applicationJSF 应用程序中的 CPU 使用率极高
【发布时间】:2014-08-18 22:05:55
【问题描述】:

我想就基于 JSF 的应用程序可能的性能改进征求意见。我们正在使用 Mojarra 实现 2.2.7。除了它,我们还有 Hibernate (4.2.7.Final)、Spring (3.2.3.RELEASE)、组件库 Proimefaces (4.0) 和实用程序库 Omnifaces (1.8),但它们不是这里的重点。我们将所有内容部署在 Jetty 服务器 8.0.0.M0 上用于测试目的,并在 Tomcat 7,0 上进行生产。

我们的界面相对复杂,因为它有很多组件和对话框。我们尝试将所有这些不同组件的代码保存在单独的 bean 中。我们在可能的情况下使用了请求范围的 bean,但最终使用了许多视图范围的 bean,主要是因为我们需要与这些组件和对话框中的数据进行交互,并且这些交互的结果要通过 ajax 立即显示(例如,当喜欢某事,更新点赞数;关注此人时,更新状态等)。一页上总共使用了 25 个视图范围的 bean(我在一个用 @PostConstruct 注释的方法中监视了它们的初始化)。此外,我们坚持使用许多复合组件,仅在必要时使用(其中大约 15 个,但其中有几个多次使用)。

我们开发了 JMeter 压力测试来检查应用程序的性能。但是,在 Amazon m1.medium 实例上,4 个并行用户的 CPU 负载达到 100%,并且一些请求失败。为了识别问题,我们在本地对其进行了分析,只有一个真实用户执行一些基本的应用程序操作。结果表明 2 种方法的 CPU 使用率很高: - javax.faces.application.ViewHandlerWrapper.restoreView (30-40%) - org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter (25-30%)

查看 JProfiler 调用图、热点和调用树,我们没有发现任何对此类 CPU 使用有重大影响的自定义方法。

这些结果在开始时甚至更糟,但在阅读并应用了我们发现的与 JSF 性能相关的一些建议后,我们设法稍微改进了它,这主要是因为更改了 bean 的范围并删除了一些不必要的组件。

我们还尝试将 javax.faces.STATE_SAVING_METHOD 设置为“客户端”和“服务器”,但没有得到任何改进。 这是我们当前的 web.xml:https://db.tt/Aw7L9ZYi

与 CPU 使用相比,堆使用似乎不是问题。 总结一下这个问题:这个问题是否与我们的代码可能的不良设计有关,还是 JSF(Mojarra 实现)的性能问题?在一页上使用许多不同的(视图范围的)bean 是否存在问题?是否还有其他可能影响 CPU 使用并且我们应该尝试解决问题的方法?我希望有人能给我一些建议,因为我们尝试了所有可以在网上找到的东西,但不知道下一步该怎么做。

谢谢

【问题讨论】:

  • 感谢您的评论。我不确定 partialSubmit 的想法是什么,以及在我们的案例中它会改进什么。我们没有任何数据,大多数请求最多有 6-7 个参数,包括 javax.faces.* 参数。如果我理解 partialSubmit 的想法,它应该适用于那些具有许多不需要处理的输入字段的表单。尽管每个请求都有 javax.faces.partial.execute=@all 并且还执行某些页面区域的渲染。您认为这会影响性能吗?如果会,应该如何改进?
  • 我的意思是,如果你没有指定进程标签参数,那么 Ajax PrimeFaces Core 将处理表单的所有输入,所以如果你的应用程序只使用 1 个表单,指定要处理的确切区域应该提高性能,但鉴于您确定您只发送了几个参数,那么就可以了
  • mojarra 本身不太可能是这种 CPU 拖累的来源。从历史上看,内存使用一直是引起关注的主要原因,而且那是在非常古老的日子里。但是,您对 mojarra 的使用可能完全是另外一个问题。
  • @kolossus 我不确定是什么问题,但我在几个来源中发现 CPU 利用率曾经是 Mojarra 的问题,主要是由于复杂组件的状态序列化/反序列化导致的开销树状结构。这也可能是这里的问题,因为我的页面很复杂并且有很多组件。但是,我不确定是否可以显着减少组件数量。我认为将部分页面设为无状态可能会有所帮助,但似乎我不能只使某些表单无状态,而其他表单在同一页面上保持有状态。

标签: java performance jsf primefaces mojarra


【解决方案1】:

请尝试添加这些参数

<context-param>// must find the equivalent for majorra
    <param-name>org.apache.myfaces.CHECK_ID_PRODUCTION_MODE</param-name>
    <param-value>true</param-value>
</context-param>  
<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Production</param-value>
</context-param>
<context-param>// must find the equivalent for majorra
    <param-name>org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE</param-name>
    <param-value>soft</param-value>
</context-param>
<context-param>
        <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
        <param-value>false</param-value>
</context-param>    
<context-param>
        <param-name>javax.faces.SERIALIZE_STATE_IN_SESSION</param-name>
        <param-value>false</param-value>
</context-param>       
<context-param>
  <param-name>facelets.REFRESH_PERIOD</param-name>
  <param-value>999999</param-value>
</context-param> 

【讨论】:

  • 感谢您的建议。我试过这个,但没有明显的改善。这是db.tt/mD3e0edT 之前和此更改db.tt/9TTh148l 之后的热点图。你还有什么想法吗?
  • 调试模式下1个请求的持续时间是多少?
  • CHECK_ID_PRODUCTION_MODE 我不确定你应该输入 true 还是 false
  • CHECK_ID_PRODUCTION_MODE 是真还是假都没有区别。请求的持续时间取决于请求的类型,介于 100ms 和 1s 之间。这是我在测试db.tt/v0eFqu8h 期间执行的请求的完整列表。我不明白调试模式是什么意思。此响应是在 PRODUCTION_MODE 设置为 Production 时做出的。
  • 我的意思是在 Eclipse 中,对我来说你的请求持续时间看起来不错,我认为我能帮助你的不仅仅是这个
猜你喜欢
  • 2023-01-19
  • 2013-04-12
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多