JMS MessageDriven bean - 如何同步线程?
JMS MessageDriven bean - how to synchronize threads?
尽管消息驱动 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 中持久化并且两条消息都是在 "if logic".
捕获
如果我的话题很混乱,不适合,请指教。
[编辑] 到目前为止我得到的是:
服务器中有一个 MessageDriven Beans (MDB) 池,对于到达的 2 条消息,您将同时获得 2 个 MDB 运行,因此您将保留相同的信息 2 次。
我在注释消息驱动 Bean 中使用了一个名为 maxSession 的属性
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")
现在池中只有一个 MDB,我在负责检查 'username' 登录审计的所有逻辑的方法中放置了一个 SYNCHRONIZED。
[编辑 2] 根据下面尼古拉斯的观察:
删除了池限制,我创建了一个用于数据库检查的静态方法(检查用户名是否存在或是否需要创建和保留)。
静态,因为它需要与 MDB 的所有实例共享,并且还同步以避免在 DB 中重复条目。
谢谢
在不知道这段代码实际应该做什么的情况下,MDB 似乎仍然是实现同步的错误位置。据推测,您将拥有有限数量的用户,并且您将为每个用户处理多条消息。通过将 MDB 池限制为一个实例,您将严重限制 MDB 处理器上的吞吐量。
与其尝试在 MDB 中同步,我建议您查看在用户名持久性机制中实现同步,或者按照您在代码中的描述:
Creates a new entry at database for 'username'
这样,可以并发处理多条消息,但是当 fortune 决定哪个线程保存用户名时,它们会短暂阻塞,(一个保存,然后获取,其他等待,然后获取) .之后,您将不会多次阻止单个用户名,并且您可以 运行 一个完整的 MDB 池。
尽管消息驱动 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 中持久化并且两条消息都是在 "if logic".
捕获如果我的话题很混乱,不适合,请指教。
[编辑] 到目前为止我得到的是:
服务器中有一个 MessageDriven Beans (MDB) 池,对于到达的 2 条消息,您将同时获得 2 个 MDB 运行,因此您将保留相同的信息 2 次。
我在注释消息驱动 Bean 中使用了一个名为 maxSession 的属性
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")
现在池中只有一个 MDB,我在负责检查 'username' 登录审计的所有逻辑的方法中放置了一个 SYNCHRONIZED。
[编辑 2] 根据下面尼古拉斯的观察:
删除了池限制,我创建了一个用于数据库检查的静态方法(检查用户名是否存在或是否需要创建和保留)。
静态,因为它需要与 MDB 的所有实例共享,并且还同步以避免在 DB 中重复条目。
谢谢
在不知道这段代码实际应该做什么的情况下,MDB 似乎仍然是实现同步的错误位置。据推测,您将拥有有限数量的用户,并且您将为每个用户处理多条消息。通过将 MDB 池限制为一个实例,您将严重限制 MDB 处理器上的吞吐量。
与其尝试在 MDB 中同步,我建议您查看在用户名持久性机制中实现同步,或者按照您在代码中的描述:
Creates a new entry at database for 'username'
这样,可以并发处理多条消息,但是当 fortune 决定哪个线程保存用户名时,它们会短暂阻塞,(一个保存,然后获取,其他等待,然后获取) .之后,您将不会多次阻止单个用户名,并且您可以 运行 一个完整的 MDB 池。