简体   繁体   English

JMS MessageDriven bean-如何同步线程?

[英]JMS MessageDriven bean - how to synchronize threads?

Despite the fact messagedriven bean is based on asynchronous logic, I have the following scenario: 尽管消息驱动bean基于异步逻辑,但我有以下情形:

  1. 2 realms containing user credentials (jdbc and ldap) 2个包含用户凭证(jdbc和ldap)的领域
  2. When user put Username and Password at form, it tries to autenticate in both realms (jdbc and ldap) 当用户在表单上放置用户名和密码时,它将尝试在两个领域(jdbc和ldap)中进行自定义
  3. For each realm attempt to login, I send a message with JMS to log it 对于每次尝试登录的领域,我都会通过JMS发送一条消息来进行记录

My problem lies at onMessage(Message message) overrided method. 我的问题在于onMessage(Message message)重写的方法。

Considering Java-Pseudocode below for a JMS Message Bean: 考虑下面的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
    }
}

Now my issue scenario: 现在我的问题场景:

  1. I put my username and password in the form and press Login 我在表单中输入了用户名和密码,然后按登录
  2. attempt to login at JDBC and fires a JMS to log it 尝试登录JDBC并触发JMS进行记录
  3. attempt to login at LDAP and fires a JMS to log it 尝试登录LDAP并触发JMS进行记录
  4. onMessage receives 2 messages (item 2 and 3) almost at sametime onMessage几乎同时接收2条消息(项目2和3)
  5. Message 1 creates a new user since it doesnt exist at database 消息1创建一个新用户,因为它在数据库中不存在
  6. Message 2 also creates a new user with same username 消息2还创建了一个具有相同用户名的新用户

I need that Message 2 uses the created user (else logic) on Message 1 (if logic), but I think that it(message 2) is so fast that entry is not persisted yet at DB and both message are catched at "if logic". 我需要消息2在消息1(如果是逻辑)上使用创建的用户(其他逻辑),但我认为它(消息2)是如此之快,以至于条目尚未在DB上持久存在,并且两条消息都在“如果逻辑上”被捕获。 ”。

Please advice if my topic is confuse and not appropriated. 如果我的主题混乱并且不适当,请提出建议。

[EDIT] Until now what I've got: [编辑]到现在为止我得到了:

There is a POOL of MessageDriven Beans (MDB) in the server, for 2 messages arriving you will get 2 MDBs running at the same time, so you will persist the same information 2 times. 服务器中有一个MessageDriven Bean(MDB)的POOL,对于2条消息到达,您将同时运行2个MDB,因此,您将相同的信息保留2次。

I used an attribute called maxSession in my Annotation Message Driven Bean 我在注释消息驱动的Bean中使用了名为maxSession的属性

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

Now I have only one MDB at the pool and I put a SYNCHRONIZED at the method responsible for checking all the logic for the 'username' login audit. 现在,我在池中只有一个MDB,并且在用于检查“用户名”登录审核的所有逻辑的方法上放置了SYNCHRONIZED。

[EDIT 2] As per observed by Nicholas below: [编辑2]根据尼古拉斯的观察,

Removed pool restriction and I created a static method for database check (check if username exists or needs to be created and persisted). 删除了池限制,我创建了一个用于数据库检查的静态方法(检查用户名是否存在或需要创建并保留)。

Static because it needs to be shared with all instances of the MDB and also Synchronized to avoid duplicating entries at DB. 静态的,因为它需要与MDB的所有实例共享,并且还需要进行同步以避免在DB上重复条目。

Thank you 谢谢

Without knowing what this code is actually supposed to be doing, it still seems that the MDB is wrong place to implement synchronization. 在不知道此代码实际上应该做什么的情况下,似乎MDB仍然是实现同步的错误位置。 Presumably, you will have a finite number of users and you will be processing multiple messages per user. 据推测,您将拥有有限数量的用户,并且每个用户将处理多个消息。 By restricting the MDB pool to one instance, you are seriosuly limiting the throughput on the MDB processor. 通过将MDB池限制为一个实例,可以极大地限制MDB处理器上的吞吐量。

Rather than trying to synchronize in the MDB, I suggest you look at implementing the synchronization in the username persistence mechanism, or as you described it in your code: 建议您不要尝试在MDB中进行同步,而应考虑在用户名持久性机制中实现同步,或者如您在代码中所描述的那样:

Creates a new entry at database for 'username'

That way, multiple messages can be processed concurrently, but they will briefly block while fortune decides which thread gets to save the username, (one will save it, then get it, the others will wait and then get it). 这样,可以同时处理多条消息,但是它们将短暂阻塞,而命运决定哪个线程可以保存用户名(一个将保存该用户名,然后获取它,其他线程将等待然后再获取它)。 After that you won't ever block for a single username more than once and you can run a full pool of MDBs. 在那之后,您将不会多次阻止单个用户名,并且您可以运行完整的MDB池。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM