尽管消息驱动bean基于异步逻辑,但我有以下情形:


2个包含用户凭据(jdbc和ldap)的领域
当用户在表单上放置用户名和密码时,它将尝试在两个领域(jdbc和ldap)中进行自定义
对于每次尝试登录的领域,我都会通过JMS发送一条消息来进行记录


我的问题在于onMessage(Message message)重写的方法。

考虑下面的JMS消息Bean的Java伪代码:

public void onMessage(Message message){
    String username = (cast message to Map and get username);
    Login login = (Login)loginDAO.filter( queryByUsername, username );
    if( login == null ){
        Creates a new entry at database for 'username'
    }else{
        Uses 'username' already created
    }
}


现在我的问题场景:


我在表单中输入了用户名和密码,然后按登录
尝试登录JDBC并触发JMS进行记录
尝试登录LDAP并触发JMS进行记录
onMessage几乎同时接收2条消息(项目2和3)
消息1创建一个新用户,因为它在数据库中不存在
消息2还创建了一个具有相同用户名的新用户


我需要消息2在消息1(如果是逻辑)上使用创建的用户(其他逻辑),但是我认为它(消息2)是如此之快,以至于条目尚未在DB上持久化,并且两个消息都在“如果逻辑上”被捕获。 ”。

如果我的主题混乱并且不适当,请提出建议。

[编辑]到现在为止,我得到了:

服务器中有一个MessageDriven Bean(MDB)的POOL,如果有2条消息到达,则您将同时运行2个MDB,因此您将相同的信息保留2次。

我在注释消息驱动的Bean中使用了名为maxSession的属性

@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")


现在,我在池中只有一个MDB,并在负责检查“用户名”登录审核的所有逻辑的方法上放置了SYNCHRONIZED。

[编辑2]根据尼古拉斯的观察,

删除了池限制,我创建了一个用于数据库检查的静态方法(检查用户名是否存在,或者是否需要创建和保留用户名)。

静态的,因为它需要与MDB的所有实例共享,并且还需要进行同步以避免在DB上重复条目。

谢谢

最佳答案

在不知道此代码实际上应该做什么的情况下,似乎MDB仍然是实现同步的错误位置。据推测,您将拥有有限数量的用户,并且每个用户将处理多个消息。通过将MDB池限制为一个实例,可以极大地限制MDB处理器上的吞吐量。

建议您不要尝试在MDB中进行同步,而应考虑在用户名持久性机制中实现同步,或者按照代码中的描述进行同步:

Creates a new entry at database for 'username'


这样,可以同时处理多个消息,但是它们将短暂阻塞,而命运决定哪个线程可以保存用户名(一个将保存该用户名,然后获取该用户名,其他线程将等待然后再获取它)。之后,您将不会多次阻止单个用户名,并且您可以运行完整的MDB池。

07-22 06:24
查看更多