20

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

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

所以我面临的问题是,当用户按下更新按钮时,只有来自他的服务器节点的缓存单例被更新。我的问题是,让其他单身人士(在其他节点中)也更新那里的数据的最简单方法是什么?

我知道Cluster environment 中的 Singleton问题,但我的问题是 Glassfish 特有的(因为我希望有一些内置支持),另一个带有“Websphere”标签。我的问题是关于 JEE6,另一个比 JEE6 更老。

4

3 回答 3

10

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

限制

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

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

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

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

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

于 2012-06-20T14:13:40.560 回答
7

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

下面是一个使用 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();

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

于 2012-06-19T11:44:35.513 回答
3

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

您可以查看此处的示例用法JGroups

于 2012-06-20T12:40:16.373 回答