Clustered Singleton using Wildfly?

2019-01-20 03:52发布

问题:

I'm trying to create a simple clustered Singleton on Wildfly 8.2. I've configured 2 Wildfly instances, running in a standalone clustered configuration. My app is deployed to both, and I'm able to access it with no problem.

My clustered EJB looks like this:

@Named
@Clustered
@Singleton
public class PeekPokeEJB implements PeekPoke {

    /**
     * Logger for this class
     */
    private static final Logger logger = Logger
            .getLogger(PeekPokeEJB.class);

    private static final long serialVersionUID = 2332663907180293111L;

    private int value = -1;

    @Override
    public void poke() {
        if (logger.isDebugEnabled()) {
            logger.debug("poke() - start"); //$NON-NLS-1$
        }

        Random rand = new SecureRandom();
        int newValue = rand.nextInt();
        if (logger.isDebugEnabled()) {
            logger.debug("poke() - int newValue=" + newValue); //$NON-NLS-1$
        }

        this.value = newValue;

        if (logger.isDebugEnabled()) {
            logger.debug("poke() - end"); //$NON-NLS-1$
        }
    }

    @Override
    public void peek() {
        if (logger.isDebugEnabled()) {
            logger.debug("peek() - start"); //$NON-NLS-1$
        }

        if (logger.isDebugEnabled()) {
            logger.debug("peek() - value=" + value); //$NON-NLS-1$
        }

        if (logger.isDebugEnabled()) {
            logger.debug("peek() - end"); //$NON-NLS-1$
        }
    }
}

...and I've written a very simple RESTful service to let me call these methods through the browser...

@Path("/test")
@Named
public class TestRS extends AbstractRestService {
    /**
     * Logger for this class
     */
    private static final Logger logger = Logger.getLogger(TestRS.class);

    @Inject
    private PeekPoke ejb = null;

    @GET
    @Path("/poke")
    public void poke() {
        if (logger.isDebugEnabled()) {
            logger.debug("poke() - start"); //$NON-NLS-1$
        }

        this.ejb.poke();

        if (logger.isDebugEnabled()) {
            logger.debug("poke() - end"); //$NON-NLS-1$
        }
    }

    @GET
    @Path("/peek")
    public void peek() {
        if (logger.isDebugEnabled()) {
            logger.debug("peek() - start"); //$NON-NLS-1$
        }

        this.ejb.peek();

        if (logger.isDebugEnabled()) {
            logger.debug("peek() - end"); //$NON-NLS-1$
        }
    }
}

I'm able to call both the peek and poke methods from a single Wildfly instance and get the expected value. However, if I attempt to call poke from one instance, and peek from another I see that the values are not being replicated across the EJBs.

I was under the impression that a clustered singleton would replicate the value of 'value' across both application servers, providing the same value regardless of which host I made the peek call from. Is this not correct? Is there something I'm missing that still needs to be added to this code?

I'd appreciate any help you can give me! Thanks!

回答1:

Singleton session beans provide a formal programming construct that guarantees a session bean will be instantiated once per application in a particular Java Virtual Machine (JVM).

The JSR 318: Enterprise JavaBeans TM ,Version 3.1 says:

A Singleton session bean is a session bean component that is instantiated once per application. In cases where the container is distributed over many virtual machines, each application will have one bean instance of the Singleton for each JVM

Hence, in a clustered application, each cluster member will have its own instance of singleton session beans and data is not shared across JVM instances (in Wildfly implementation).

In Wildfly if you need only one instance of singleton in a cluster scope you can use the SingletonService implementation. Using a SingletonService, the target service is installed on every node in the cluster but is only started on one node at any given time.

See:

  • Implement an HA Singleton
  • cluster-ha-singleton: A SingletonService deployed in a JAR started by SingletonStartup and accessed by an EJB

UPDATE:

WildFly 10 adds the ability to deploy a given application as a "singleton deployment". This is a new implementation of a feature that existed in AS 6.0 and earlier. When deployed to a group of clustered servers, a singleton deployment will only deploy on a single node at any given time. If the node on which the deployment is active stops or fails, the deployment will automatically start on another node.

See: WildFly 10 Final is now available!