如何通知Glassfish 3.1集群中的所有(相同)Singleton bean?

时间:2012-06-17 09:00:01

标签: java java-ee synchronization glassfish cluster-computing

我有一个在Glassfish 3.1.2集群上运行的JEE6应用程序。 一个@Singleton Bean包含某种(readolny)缓存。用户可以按下GUI中的按钮,使用数据库中的(更新的)内容更新缓存。

这在非集群环境中运行良好,但现在我们需要切换到集群。

所以我面临的问题是,当用户按下该更新按钮时,只更新其服务器节点中的Cache Singleton。我的问题是,让其他Singletons(在其他节点中)更新数据的最简单方法是什么?

我知道问题Singleton in Cluster environment,但我的问题是针对Glassfish的(因为我希望有一些内置支持),另一个是“Websphere”。我的问题是关于JEE6,另一个比JEE6旧。

3 个答案:

答案 0 :(得分:10)

GlassFish High Availability Administration Guide明确指出:

  

<强>限制

     

配置会话持久性和故障转移时,请注意以下事项   限制:

     
      
  • 会话故障转移时,对打开文件或网络连接的任何引用都将丢失。应用程序必须考虑到此限制条件。

  •   
  • 为群集中的每个服务器实例创建EJB单例,而不是每个群集创建一次。

  •   

另一个建议是使用 JMS 并按GUI按钮将消息发布到JMS主题。所有Singleton bean都可以订阅该主题,并且接收消息将使它们几乎同时从数据库更新。这种方法的好处是它可以利用Glassfish的更多内置功能,而不必引入另一个框架。

在任何情况下,从单个实例移动到多个实例永远不会是真正的无缝更改,并且会导致一些困难。可能需要进行应用程序更改,以确保所有相关状态(会话状态除外)正确共享到群集中的所有实例。

答案 1 :(得分:7)

遗憾的是,没有内置的方法可以实现您的目标,但Glassfish基于其构建的shoal框架可以帮助您解决问题。您可以通过向集群成员发送通知来更新其缓存或将当前缓存替换为分布式缓存来解决问题。

以下是使用浅滩发送通知的示例:

@Startup
@Singleton
public class Test {

private String groupName = "mygroup";
private String serverName = System.getProperty("HTTP_LISTENER_PORT");
private GroupManagementService gms;

@PostConstruct
public void init() {
    Runnable gmsRunnable = GMSFactory.startGMSModule(serverName, groupName,
            GroupManagementService.MemberType.CORE, null);
    gms = (GroupManagementService) gmsRunnable;
    try {
        gms.join();
        gms.addActionFactory(new MessageActionFactory() {

            @Override
            public Action produceAction() {
                return new MessageAction() {

                    @Override
                    public void consumeSignal(Signal signal)
                            throws ActionException {
                        // Update your cache here
                    }
                };
            }
        }, groupName);
    } catch (GMSException e) {
        Logger.getAnonymousLogger().severe(e.getMessage());
    }
}

@PreDestroy
public void cleanup() {
    gms.shutdown(GMSConstants.shutdownType.INSTANCE_SHUTDOWN);
}

/**
 * Call this from your button click.
 */
public void updateCache() {
    try {
        byte[] message = new byte[] {};
        gms.getGroupHandle().sendMessage(groupName, message);
    } catch (GMSException e) {
        Logger.getAnonymousLogger().severe(e.getMessage());
    }
}
}

如果您想使用分布式缓存:

            DistributedStateCache cache = gms.getGroupHandle().getDistributedStateCache();

放置在缓存中的项目将复制到其他群集节点。

答案 2 :(得分:3)

看看JGroups。它是可靠的多播通信的框架。 JBoss集群机制目前基于此工具。

您可以查看example usage of JGroups here