WELD + GF4 + SessionScoped:有时会错误的bean? [英] WELD + GF4 + SessionScoped: Sometimes wrong bean?
问题描述
TL; DR 我们得到了 最近,我们的两个客户系统遇到了严重的问题。我们的客户在两台拥有带WELD 2.0.5的Glassfish 4.0服务器的机器上运行同一个JSF 2.2应用程序的两个独立实例(对内存泄漏记忆犹新!)。 有些用户报告出现问题后,提交表单的响应显示的是另一个用户名,而不是最初登录的用户名。由于我们无法在开发和测试环境中重现此行为,因此我们开始从生产系统获取日志数据。 我们记录的是什么? 在我们的第一次尝试中,我们开始记录哪个用户从哪个客户端有些时候。在浏览日志后,我们发现了如下的序列: 在更换发生之前,替换用户的会话(这里 关于第一个日志功能,我们开始看到序列显示来自session scoped bean的用户名和存储在HTTP session内的值之间的实际差异: 将所有处理请求计入帐户,会话范围值与会话值不匹配的值大约为。在60到150个请求中有1个。 更有趣的是 我们没有想到有时在 最初我们认为这些事件更有可能发生在服务器负载一段时间后,但事实证明这并非如此。有时它们会在最后一次服务器重启后几小时发生,有时会在两周后发生。 通过在互联网上搜索这些问题,我们无法找到其他遇到相同问题或WELD中已知错误的人的实际痕迹(<a href =https: //issues.jboss.org/browse/WELD-1691rel =noreferrer>最好的痕迹,但错误的版本),Glassfish,Grizzly(最好的追踪,但太旧了),JSF等等 是:有没有人遇到过类似的问题?这种奇怪的行为是不是某种我们试图在错误的地方发现的已知错误?是否有一个实际的修复?任何提示都非常感谢! 更新: 我们发现,如果我们重新启动整个机器,已经过去了两个星期左右。如果我们只是重新启动Glassfish,那么在奇怪的行为回来之前,这只是一个小时的问题。严重的是,什么会影响Glassfish或JVM,使得只有机器重启才会改变行为? 目前我们通过将所有保存在 而不是像这样注入session scoped bean: 试着用这种方式注入它: TL;DR We get lately we have been experiencing serious problems with two of our customer systems. Our customers are running two independent instances of the same JSF 2.2 application on two machines having a Glassfish 4.0 Server with WELD 2.0.5 (hail to the memory leak!). Some users have been reporting problems that after e.g. submitting a form the response shows another user name than the one who initially logged in. Since we were unable to reproduce this behaviour in our development and testing environments, we started to grab log data from the productive systems. What were we logging? On our first attempt we started logging which user conducted which action from which client at some time. After crawling through the logs we found sequences like this: Whereas the session of the replacing user (here Therefore on our second attempt we extended the log data by the following features: Regarding the first log feature we started seeing sequences showing actual differences between the user name coming from the session scoped bean and the value being stored inside the HTTP session: Taking all requests being processed into account, the ones where the session scope value does not match the session value are approx. 1 out of 60 to 150 requests. More interesting is what happened with the We did not expect that sometimes after the Initially we assumed that these events are more likely to occur after the server has been under load for a while, but this turned out not to be true. Sometimes they occur some hours after the last server restart and sometimes after two weeks. Searching the internet for these issues we were not able to find actual traces on other people experiencing the same problems or known bugs in either WELD (best trace, but wrong version), Glassfish, Grizzly (best trace, but too old), JSF, etc. So our question is: Is there anyone who ever has experienced a similar problem? Is this odd behaviour somehow a known bug we just tried to identify in the wrong spot? Is there even an actual fix? Any hint is gladly appreciated! Update: We found out that if we restart the whole machine the described behaviour is gone for around two weeks. If we just restart Glassfish it's a matter of hours until the odd behaviour is back. Seriously, what can affect Glassfish or the JVM that badly such that only a machine reboot changes the behaviour? Currently we are bypassing the problem by putting all data we kept in the Instead of injecting the session scoped bean this way: Try to inject it this way:
这篇关于WELD + GF4 + SessionScoped:有时会错误的bean?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! @SessionScoped
会话
时间客户端用户操作
....... ......................
t = 0 ClientA UserA登录
t = 1 ClientA UserA注销
t = 2 ClientB UserB登录
t = 3 ClientB UserB ActionA
t = 4 ClientB * UserA * ActionB
t = 5 ClientB UserB Logoff
User A
)并不总是结束(有时会导致一个用户注销另一个用户...)。那么当前登录的用户存储在哪里?我们将它作为一个属性存储在一个 @SessionScoped
bean中,并被注入到 @RequestScoped
bean中,只要我们需要这些信息。这导致我们理解 @SessionScoped
bean有时会混淆。
@Named
$ p $因此,在我们的第二次尝试中,我们通过以下功能扩展了日志数据:
@ javax.enterprise.context.SessionScoped
public class SessionStateBean {
private用户用户;
public void setUser(...){}
public User getUser(){}
}
@SessionScoped
bean的值进行比较。
@SessionScoped
bean实例都收到它自己的UUID,并在bean构建时记录下来&销毁以及用户资产被更改时。我们知道 @SessionScoped
bean可能有多个代理,被钝化等,但我们试了一下。
时间会话客户端用户操作
..................... ........
t = 0 SessA ClientA UserA登录
t = 1 SessA ClientA UserA Logoff
t = 2 SessB ClientB UserB登录
t = 3 SessB ClientB UserB ActionA
t = 4 | SessB ClientB * UserA * ActionB
+ - > SessionScope!= Session
t = 5 SessB ClientB UserB Logoff
@SessionScoped
bean实例发生了什么。由于我们正在跟踪 @PostConstruct
& @PreDestroy
事件,观察到如下序列:
时间会话Bean操作UserValue
................................
t = 0 SessA BeanA构造(null )
t = 1 SessA BeanA SetUser UserA // login
t = 2 SessA BeanA SetUser(null)//注销
t = 3 SessA BeanA Destroy(null)
//到目前为止好,现在它变得有趣
t = 4 SessB BeanA SetUser UserB //登录
t = 5 SessB BeanA SetUser(null)//注销
t = 6 SessC BeanA SetUser UserC // login
t = 7 SessC BeanA SetUser(null)//注销
t = 8 SessD BeanA SetUser UserD //登录
t = 9 SessD BeanA SetUser(null)//注销
@PreDestroy
事件bean实例获得重用之后没有经历建设和破坏的生命周期。考虑到所有记录的bean实例, 500(系统A)至4000(系统B)中的1个bean。当会话范围值和HTTP会话值不同时,这并不总是发生,但总是当我们看到这样的一个bean实例被重用时,它就是值的不同。
@SessionScoped
bean中的数据直接放到HTTP会话中并绕过这个问题,目前为止似乎工作正常。但是这种方法太笨拙了......
@Inject
private SessionBean sessionBean;
@Inject
private实例< SessionBean>一个sessionBean;
@SessionScoped
bean instances injected that have the content of another session
Time Client User Action
.............................
t=0 ClientA UserA Login
t=1 ClientA UserA Logoff
t=2 ClientB UserB Login
t=3 ClientB UserB ActionA
t=4 ClientB *UserA* ActionB
t=5 ClientB UserB Logoff
User A
) was not always over before the replacement happened (sometimes resulting in one user logging out another one...). So where is the currently logged in user stored? We store it as a property in a @SessionScoped
bean being injected into @RequestScoped
beans wherever we need this information. This led us to the theory that the @SessionScoped
beans sometimes get mixed up.@Named
@javax.enterprise.context.SessionScoped
public class SessionStateBean {
private User user;
public void setUser(...) { }
public User getUser() { }
}
@SessionScoped
bean.@SessionScoped
bean received its own UUID and logged when the bean was constructed & destroyed as well as when the user property was changed. We know that it is possible that @SessionScoped
beans can have multiple proxies, be passivated, etc., but we gave it a try.Time Session Client User Action
.............................
t=0 SessA ClientA UserA Login
t=1 SessA ClientA UserA Logoff
t=2 SessB ClientB UserB Login
t=3 SessB ClientB UserB ActionA
t=4 |SessB ClientB *UserA* ActionB
+-> SessionScope != Session
t=5 SessB ClientB UserB Logoff
@SessionScoped
bean instances. Since we are tracking @PostConstruct
& @PreDestroy
events, sequences like the following were observed:Time Session Bean Action UserValue
................................
t=0 SessA BeanA Construct (null)
t=1 SessA BeanA SetUser UserA // login
t=2 SessA BeanA SetUser (null) // logout
t=3 SessA BeanA Destroy (null)
// so far so good, now it gets interesting
t=4 SessB BeanA SetUser UserB // login
t=5 SessB BeanA SetUser (null) // logout
t=6 SessC BeanA SetUser UserC // login
t=7 SessC BeanA SetUser (null) // logout
t=8 SessD BeanA SetUser UserD // login
t=9 SessD BeanA SetUser (null) // logout
@PreDestroy
event bean instances get reused without going through the life cycle of construction and destruction. Taking all logged bean instances into account this happens with approx. 1 bean out of 500 (System A) to 4000 (System B). This is not always happening when the session scope value and the HTTP session value differ, but always when we see such a bean instance being reused it is when the values are different.
@SessionScoped
bean directly into the HTTP session and so far it seems to work fine. But that approach is so clumsy...@Inject
private SessionBean sessionBean;
@Inject
private Instance<SessionBean> sessionBean;