使用 Wildfly 的集群单例?
Clustered Singleton using Wildfly?
我正在尝试在 Wildfly 8.2 上创建一个简单的集群 Singleton
。我在独立集群配置中配置了 2 个 Wildfly 实例 运行。我的应用程序已部署到两者,我可以毫无问题地访问它。
我的集群 EJB 如下所示:
@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$
}
}
}
...我写了一个非常简单的 RESTful 服务让我通过浏览器调用这些方法...
@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$
}
}
}
我能够从单个 Wildfly 实例调用 peek
和 poke
方法并获得预期值。但是,如果我尝试从一个实例调用 poke,并从另一个实例中查看,我会发现这些值没有在 EJB 之间复制。
我的印象是集群单例会在两个应用程序服务器之间复制“value
”的值,无论我从哪个主机发出 peek
调用都提供相同的值。这不对吗?是否有我遗漏的东西需要添加到此代码中?
如果您能给我任何帮助,我将不胜感激!谢谢!
单例会话 bean 提供了一种正式的编程结构,保证会话 bean 在特定的 Java 虚拟机中 每个应用程序 实例化一次( JVM).
JSR 318:企业 JavaBeans TM,版本 3.1 说:
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
因此,在集群应用程序中,每个集群成员都有自己的单例会话 bean 实例,并且数据不会在 JVM 实例之间共享(在 Wildfly 实现中)。
在 Wildfly 中,如果您在集群范围内只需要一个单例实例,则可以使用 SingletonService
实现。使用 SingletonService
,目标服务安装在集群中的每个节点上,但在任何给定时间仅在一个节点上启动。
参见:
- Implement an HA Singleton
- cluster-ha-singleton: 部署在 JAR 中的 SingletonService 已启动
通过 SingletonStartup 并通过 EJB
访问
更新:
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.
我正在尝试在 Wildfly 8.2 上创建一个简单的集群 Singleton
。我在独立集群配置中配置了 2 个 Wildfly 实例 运行。我的应用程序已部署到两者,我可以毫无问题地访问它。
我的集群 EJB 如下所示:
@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$
}
}
}
...我写了一个非常简单的 RESTful 服务让我通过浏览器调用这些方法...
@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$
}
}
}
我能够从单个 Wildfly 实例调用 peek
和 poke
方法并获得预期值。但是,如果我尝试从一个实例调用 poke,并从另一个实例中查看,我会发现这些值没有在 EJB 之间复制。
我的印象是集群单例会在两个应用程序服务器之间复制“value
”的值,无论我从哪个主机发出 peek
调用都提供相同的值。这不对吗?是否有我遗漏的东西需要添加到此代码中?
如果您能给我任何帮助,我将不胜感激!谢谢!
单例会话 bean 提供了一种正式的编程结构,保证会话 bean 在特定的 Java 虚拟机中 每个应用程序 实例化一次( JVM).
JSR 318:企业 JavaBeans TM,版本 3.1 说:
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
因此,在集群应用程序中,每个集群成员都有自己的单例会话 bean 实例,并且数据不会在 JVM 实例之间共享(在 Wildfly 实现中)。
在 Wildfly 中,如果您在集群范围内只需要一个单例实例,则可以使用 SingletonService
实现。使用 SingletonService
,目标服务安装在集群中的每个节点上,但在任何给定时间仅在一个节点上启动。
参见:
- Implement an HA Singleton
- cluster-ha-singleton: 部署在 JAR 中的 SingletonService 已启动 通过 SingletonStartup 并通过 EJB 访问
更新:
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.