分布式锁和Java EE

4
我正在使用JBoss AS 6编写Java EE应用程序,其中有一个资源需要独占访问(第三方软件的某个接口)以获取给定参数的方法。目前我在处理锁定时有些不当(因为规范禁止这样做),我正在使用java.util.concurrent.ReentrantLock
现在,我将多个JBoss应用程序服务器集群在一起,因此需要跨集群中的不同节点工作的解决方案。我认为至少有以下几种选择。
  1. 共享缓存(Infinispan)
  2. JGroups
  3. 基于文件系统的锁定(可能不好,但我们仍然依赖于共享文件系统)
  4. 数据库
  5. Singleton EJB's?
理想情况下,我正在寻找高级API,以便我可以编写像这样的EJB方法
public class MyEJBBean {

    private SharedLock lock;

    public void doSomethingWithSharedResource(String s) {
        lock.lock(); // blocks until shared resource is not used by anyone else
        try {
           // Use shared resource
        } 
        finally {
           lock.unlock();
        }
    }

我有没有错过任何选项?有没有人有这种锁定机制的经验可以分享?

2个回答

2
理想情况下,我建议将第三方软件封装成单独的应用程序,在单个实例上运行。这样,您可以使用EJB单例处理锁定(我认为@Singleton在您的情况下无济于事),并使用远程EJB / WS公开它。看起来这个软件有点棘手(单线程?),因此具有更友好的EJB接口将是一个额外的好处。
想一想 - 如果您只能每次为整个系统访问库一次,那么为什么要分发它呢?总是最多只能使用一个实例。
如果您想坚持同质分布式系统(这通常不是一个坏主意),我建议使用SELECT FOR UPDATE进行数据库锁定。我从未尝试过,但我认为在使用库之前发出这样的SQL(获取锁定),然后让EJB容器提交事务(有效释放锁定)即可解决问题。

3
我们以前使用过数据库锁定技术。如果您只有一个支持集群的数据库实例,那么这是一种完全有效且廉价的锁定方法。另一个想法是将第三方服务程序放在 JMS 队列的另一端。请求被发布到队列中,服务程序对其进行处理,然后通过附加到消息的临时队列(或其他方式)将结果发布回来。显然仍然存在锁定,但它在 JMS 服务器内部,不再是应用程序的一级概念。 - Will Hartung
+1,使用单个消费者的JMS似乎是最符合JEE风格的方式,我喜欢它。 - Tomasz Nurkiewicz
这比那稍微复杂一些。API 有一个方法 foo(String s) - 该方法不能同时使用相同的 s 被调用两次。听起来是个好建议,所以明天上班时我会试试。 - Jeff Foster

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接