如何通知 Glassfish 3.1 集群中的所有(相同)单例豆?

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

这在无群集环境中效果很好,但现在我们需要切换到群集。

因此,我面临的问题是,当用户按下该更新按钮时,仅更新其服务器节点中的缓存单例。我的问题是,让其他单例(在其他节点中)也更新数据的最简单方法是什么?

我知道在集群环境中存在问题Singleton,但我的问题特定于Glassfish(因为我希望有一些内置支持),另一个被标记为“Websphere”。我的问题是关于JEE6的,另一个比JEE6更老。


答案 1

GlassFish 高可用性管理指南明确指出:

限制

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

  • 当会话故障转移时,对打开的文件或网络连接的任何引用都将丢失。应用程序在编码时必须牢记此限制。

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

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

无论如何,从单个实例移动到多个实例从来都不是一个真正无缝的改变,并且会造成一些困难。可能需要对应用程序进行更改,以确保所有相关状态(会话状态除外)都正确共享到群集中的所有实例。


答案 2

不幸的是,没有内置的方法来实现你想要的东西,但是Glassfish基于其集群的浅滩框架可以帮助你。您可以通过向集群成员发送通知以更新其高速缓存或将当前高速缓存替换为分布式高速缓存来解决此问题。

下面是一个使用浅滩发送通知的示例:

@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();

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


推荐