Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to notify all (same) Singleton beans in a Glassfish 3.1 Cluster?

Tags:

I have a JEE6 application that runs on an Glassfish 3.1.2 cluster. One @Singleton Bean contains some kind of (readolny) cache. A User can press a button in the GUI to update the cache with (updated) content from the database.

This works well in a none clustered environment, but now we need to switch to an cluster.

So I am facing the problem, that when a user press that update button, only the Cache Singleton from his server node is updated. My question is, what would be the easiest way to make the other Singletons (in the other nodes) updating there data too?

I am aware of question Singleton in Cluster environment, but my question is specific for Glassfish (because I hope there is some build in support), the other one is taged with "Websphere". And my question is about JEE6, the other one is older than JEE6.

like image 323
Ralph Avatar asked Jun 17 '12 09:06

Ralph


People also ask

How can we maintain singleton in clustered environment?

The simplest approaches are: Add an expiry timer to your singleton cache so that every so often the cache gets purged and subsquent calls fetch the updated data from source (e.g. a database) Implement a notification mechanism for the cache using something like a JMS topic/tibRV.

What are singleton clusters?

A cluster-singleton is a service that is deployed across multiple cluster nodes, which is never active in more than one node concurrently.


2 Answers

GlassFish High Availability Administration Guide explicitly states:

Restrictions

When configuring session persistence and failover, note the following restrictions:

  • When a session fails over, any references to open files or network connections are lost. Applications must be coded with this restriction in mind.

  • EJB Singletons are created for each server instance in a cluster, and not once per cluster.

Another suggestion, would be to use JMS and have the GUI button press post a message to a JMS Topic. All the Singleton beans can subscribe to that Topic and receiving the message will cause them all to update from the database, almost simultaneously. The benefit of this approach, is that it leverages more of the built in features of Glassfish, without necessarily having to bring in another framework.

In any case, moving from single instance to multiple instance is never a truly seamless change, and is going to cause some difficulty. There will probably need to be application changes to make sure that all the relevant state (other than session state), is shared correctly to all instances in the cluster.

like image 112
Sam Goldberg Avatar answered Sep 20 '22 16:09

Sam Goldberg


Unfortunately there's no built-in way of achieving what you want, but the shoal framework that Glassfish bases its clustering on could help you out here. You can solve the problem either by sending notifications to cluster members to update their caches or by replacing your current cache with a distributed one.

Below is an example using shoal to send notifications:

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

If you wanted to use a distributed cache instead:

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

Items placed in the cache will be replicated to the other cluster nodes.

like image 40
Nick Wilson Avatar answered Sep 19 '22 16:09

Nick Wilson