gpt4 book ai didi

JSF 2.2 内存消耗 : Why does Mojarra keep the ViewScoped Beans of the last 25 Views in Memory?

转载 作者:行者123 更新时间:2023-12-03 07:29:31 24 4
gpt4 key购买 nike

每个 session 的内存增长
我们在使用 JSF 2.2 (2.2.12) 和 Mojarra 时遇到了高内存消耗。在调查我们的负载测试后,我们的 ViewScoped Beans 中的数据大小非常大(有时超过 1MB)。无论如何 - 从 View 导航到 View 时, session 内存大小会不断增长。我们不能在短期内减小 bean 的大小,因此这种行为具有相当大的影响。
解决方案 1 - 更改上下文参数(不起作用)
现在 - 我们使用了 Mojarra 的官方上下文参数,默认设置为 15:

com.sun.faces.numberOfLogicalViews
com.sun.faces.numberOfViewsInSession
在我们的负载测试中,将这些参数更改为较低的值对内存消耗没有任何影响。
解决方案 2 - 更改 activeViewMapsSize(工作)
我们正在调试 Mojarra 并在 ViewScopeManager 中发现以下代码:
Integer size = (Integer) sessionMap.get(ACTIVE_VIEW_MAPS_SIZE);
if (size == null) {
size = 25;
}
保留最后访问的 View 的默认大小似乎是 25。看到这一点,我们实现了一个 session 监听器,将这个值设置为 1:
public class SetActiveViewMapsSizeSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent event) {
event.getSession().setAttribute(ViewScopeManager.ACTIVE_VIEW_MAPS_SIZE, 1);
}
}
那显然奏效了。由于只保留了 1 个 View ,因此内存停止增长。
那么为什么内存中有 25 个 View ?
因此,Mojarra 会在内存中保留 25 个 View 的历史记录,以防 Session 中没有定义不同的值。我找不到任何关于此的文档。有人可以解释一下这是做什么的吗?是浏览器返回吗?我们在 JSF 页面上禁用了缓存。因此浏览器返回将始终创建一个新 View 。这对我们来说应该不是问题。
解决方案 2 是一种有效的方法吗?有人可以解释这种方法的缺点吗?
更新 1
经过各种评论和更深入的调试,结果是:
  • com.sun.faces.numberOfLogicalViews定义逻辑 View 大小,它只存储(!)ui 组件树的状态
  • com.sun.faces.application.view.activeViewMapsSize定义 activeViewMap 的大小,它包含 ViewScoped bean

  • 更改时 numberOfLogicalViews到 1,mojarra 仍将跟踪最后 25 个 View 的所有 View 作用域 bean。当您以相反的方式配置它时 - numberOfLogicalViews到 15 和 activeViewMapsSize到 1 - 我猜由于缺少数据, View 无法正确初始化。我们甚至没有得到异常(exception)。我想明白,为什么mojarra 选择设置 activeViewMapsSize高于 numberOfLogicalViews并且不一样,因为我们希望在不出现不可预测的行为的情况下调整内存消耗。
    更新 2
    我们在 Mojarra 创建了一个问题: JAVASERVERFACES-4015 .

    最佳答案

    Why does Mojarra keep the ViewScoped Beans of the last 25 Views in Memory?


    因为网页也可以在新的浏览器选项卡中打开,而不是在当前浏览器选项卡中打开。遗憾的是,没有一种万无一失的方法可以根据普通的 HTTP GET 请求来确定 View 是在现有浏览器选项卡中打开还是在新浏览器选项卡中打开。因此,无论网页是否在同一浏览器选项卡中打开,所有关联的 bean 都保存在内存中。

    Anyway - when navigating from view to view, the session memory size grows and grows.


    如果您在同一个浏览器选项卡中从一个 View 导航到另一个 View ,这确实没有意义。但是当您在新的浏览器选项卡中打开下一个 View 时,这确实有意义。这样,当您切换回上一个浏览器选项卡并继续与那里的 View 交互时,上一个浏览器选项卡中的 View 可以继续正常工作。

    We can't decrease the size of the beans on short-term, so this behavior has quite some impact.


    从技术上讲,可以在客户端检测当前页面是否已卸载,并将此情况通知服务器。这些天, pagehide 事件可用于在客户端检查当前 View 是否已被销毁, navigator.sendBeacon 可用于以可靠的方式将这种情况通知服务器(使用例如 unloadXMLHttpRequest 的组合不太可靠,因为无法保证它是否会真正按时命中服务器)。
    这一切都在 OmniFaces @ViewScoped 背后的逻辑中实现了自 OmniFaces 2.2(2015 年 11 月)以来,多年来逐渐形成自 OmniFaces 2.7.3(2019 年 11 月)以来的当前形态。如果您已经在使用 CDI 来管理 bean,那么应该换出 import javax.faces.view.ViewScoped; 的问题。源代码中的行 import org.omnifaces.cdi.ViewScoped;为了利用这一点。在我参与过的一个项目中,自从原生 JSF View 范围 bean 迁移到 OmniFaces View 范围 bean 以来,内存使用量减少了 70%。
    也可以看看:
  • com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews
  • How detect and remove (during a session) unused @ViewScoped beans that can't be garbage collected
  • JSF: Mojarra vs. OmniFaces @ViewScoped: @PreDestroy called but bean can't be garbage collected
  • 关于JSF 2.2 内存消耗 : Why does Mojarra keep the ViewScoped Beans of the last 25 Views in Memory?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31959982/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com