7

例如,我有 DBManager.java 单例类,我必须将其部署在集群环境中。它是一个基于 Web 的应用程序,具有以下部署策略

Apache 负载均衡器 --> Tomcat 6(集群中的 3 个服务器)。

我必须为 3 个 tomcat 实例维护单个 DBManager 实例。

我的代码是

package com.db.util;
public class DBManager {
    private static DBManager singleInstance;
    private DBManager () {}
    public static DBManager getSingleInstance() {
        if (singleInstance == null) {
            synchronized (DBManager.class) {
                if (singleInstance == null) {
                    singleInstance = new DBManager ();
                }
            }
        }
        return singleInstance;
    }
}

我一直在寻找这个问题的解决方案,并找到了类似 JGroups API 的东西。这可以使用 JGroups 来实现吗?任何想法,如何实现?

4

2 回答 2

6

Java 在每个实例中为您提供了一个单例,您需要在实例之间进行某种协调,因此在任何给定时间它们中的一个处于活动状态,但如果活动的一个死了,那么另一个实例将变为活动状态。

一些应用服务器已经内置了控制这种协同工作实例的能力,我不知道Tomcat是否有这样的功能。

自己构建这样的功能非常困难,请参阅此问题并注意该问题提供了指向有用库的链接 - 在我看来,使用起来非常复杂。

但是,在您的情况下,您有一个数据库,这为您提供了一个协调点。我没有详细设计这个,但我认为可以使用控制表中的专用行来创建预订方案。有效地做到这一点会有点棘手,平衡检测实例死亡的速度与轮询数据库以查看哪个实例处于活动状态的开销,但这似乎是可行的。

这个想法是记录包含“reservedUntil”时间戳和“processId”。每个进程读取记录,如果它包含它自己的 id 并且时间戳尚未过期,它就知道它可以工作。当时间快要到期时,活动进程使用乐观锁定样式“更新其中时间戳==旧时间戳”来更新时间戳以管理竞争条件。每个非活动进程都会等待,直到它上次读取的时间戳过期,然后尝试通过更新记录来控制,再次使用乐观锁定 Update where。通常,控制权的尝试会失败,但如果成功,我们现在有一个新的活动实例,并且由于乐观锁定,我们只能获得一个活动实例。

于 2012-08-20T06:44:31.073 回答
0

Singleton 确保在给定的 JVM 中只有一个类的实例。

在您的情况下,多个 DBManager (每个 JVM 一个)有什么问题?

于 2012-08-20T06:12:42.660 回答