2017-08-07 115 views
0

我能够在我的独立集群中部署我的耳朵和战争。我的战争中有2场是为了单身人士。在开始第一个独立的jboss-eap-6后不久,我开始第二个。当我的所有应用程序都部署成功后,我打开J-Console,我注意到我的单例战争中有一个在第一个jboss-eap-6上运行,第二个单例战争在第二个jboss-eap-6上运行。另外在Jconsole中,只有1个jboss-eap-6报告为主要报告。jboss-eap-6 HA singleton在独立配置下部署多个web档案

我的问题是:jboss-eap-6 standalone.xml中是否有某种方法我只能强制一个jboss-eap-6运行单例HA战争。或者我是否必须将战争打包成耳朵?

+0

你如何在战争中定义你的HA单身人士?您是否使用ServiceActivator装饰器注册并启动HA服务?我只是有点惊讶,因为我认为这些服务不会从Web容器中获得。 –

回答

0

所以经过进一步评估后,这两个单身最终会在几分钟后合并在一起,从而创造出一个单身。

0

我不认为standalone.xml有任何东西会改变战争的行为。在任何情况下,您都应该使用standalone-ha.xml作为部署HA单例的集群。

JBoss的高可用性架构辛格尔顿的JBoss EAP 5和6

之间显著变化下的JBoss EAP 5刚才放置您的部署对象在deploy-hasingleton特殊的部署文件夹。在JBoss EAP 6中,你的类需要实现一个JBoss服务层,特别是org.jboss.msc.service.Service以及org.jboss.msc.service.ServiceActivator。正是这些服务类的实现控制了您的HA Singleton的实例化和管理。我还没有尝试过部署一个hasingleton作为战争,我有一些疑惑,因为我怀疑依赖的服务类可能在Web容器中不可用。

ServiceActivator负责管理Service的生命周期。 ServiceActivator实现类需要在文件META-INF/service/org.jboss.msc.service.ServiceActivator中列出来供JBoss在其启动/部署期间激活它。

举例: 创建服务激活

public abstract class SingletonActivator<T extends Serializable> implements ServiceActivator { 

    @Override 
    public SingletonService<String> instantiateSingleton() { 
     return new SingletonService<String>(); 
    } 

    public ServiceName getServiceName() { 
     return ServiceName.JBOSS.append("my", "ha", "singleton"); 
    } 


    /** 
    * Activated by the Service Activator 
    * 
    * @param service 
    * @param serviceName 
    *   - the Singleton Service Name that is registered in the JBOSS cluster 
    */ 
    @Override 
    public final void activate(ServiceActivatorContext context) { 
     SingletonService<T> service = instantiateSingleton(); 
     SingletonService<T> singleton = new SingletonService<T>(service, getServiceName()); 

     /* 
     * The NamePreference is a combination of the node name (-Djboss.node.name) and the name of 
     * the configured cache "singleton". If there is more than 1 node, it is possible to add more than 
     * one name and the election will use the first available node in that list. 
     */ 
     // e.g. singleton.setElectionPolicy(new PreferredSingletonElectionPolicy(new SimpleSingletonElectionPolicy(), new NamePreference("node1/singleton"))); 
     // or singleton.setElectionPolicy(new PreferredSingletonElectionPolicy(new SimpleSingletonElectionPolicy(), new NamePreference("node1/singleton"), new 
     // NamePreference("node2/singleton"))); 

     singleton.build(new DelegatingServiceContainer(context.getServiceTarget(), context.getServiceRegistry())).setInitialMode(ServiceController.Mode.ACTIVE).install(); 
    } 
} 

创建HA集服务类,它是用于查找和调用包含业务逻辑

public class SingletonService<T> implements Service<T> { 
    protected ScheduledExecutorService deployDelayThread = null; 

    /** 
    * The node we are running on 
    */ 
    protected String nodeName; 

    /** 
    * A flag whether the service is started (or scheduled to be started) 
    */ 
    protected final AtomicBoolean started = new AtomicBoolean(false); 

    /** 
    * Container life cycle call upon activation. This will construct the singleton instance in this JVM and start the Timer. 
    */ 
    @Override 
    public final void start(StartContext context) throws StartException { 
     this.nodeName = System.getProperty("jboss.node.name"); 
     logger.info("Starting service '" + this.getClass().getName() + "' on node " + nodeName); 
     if (!started.compareAndSet(false, true)) { 
      throw new StartException("The service " + this.getClass().getName() + " is still started!"); 
     } 
     // MSC does not allow this thread to be blocked so we let the service know that the start is asynchronous and the result will be advised later. 
     // We delay the actual deployment of the Singleton for a few seconds to allow time for a HASingleton Election to be held and won by one of the instances. 
     // If the winner is not this instance (prior to deployemnt) then stop(Context) is invoked which sets started to false and the deployment does not occur. 
     // context.asynchronous(); 
     deployDelayThread.schedule(new StartSingletonAsync(context), 10, TimeUnit.SECONDS); 
     context.complete(); 
    } 

    /** Introduces a 5s delay in starting the Singleton bean giving time for the the ha singleton election to be held and won */ 
    private class StartSingletonAsync implements Runnable { 

     private StartSingletonAsync(StartContext context) { 
     } 

     @Override 
     public void run() { 
      try { 
       startSingletonBean(); 
      } catch (StartException e) { 
       logger.info("Start Exception", e); 
      } 
      // be nice to the garbage collector, we don't need this any more 
      deployDelayThread.shutdown(); 
      deployDelayThread = null; 
     } 
    } 

    private void startSingletonBean() throws StartException { 
     try { 
      if (!started.get()) { 
       throw new StartException("Aborted due to service stopping"); 
      } 
      // Start your EJB 
      InitialContext ic = new InitialContext(); 
      bean = ic.lookup(getJndiName()); 
      bean.startHaSingleton(); 
      logger.info("*** Master Only: HASingleton service " + getJndiName() + " started on master:" + nodeName); 
      if (!bean.isRunning()) { 
       logger.error("ERROR Bean should be running"); 
      } 
     } catch (NamingException e) { 
      throwStartException(e); 
     } 
    } 

    private void throwStartException(Exception e) throws StartException { 
     String message = "Could not initialize HASingleton" + getJndiName() + " on " + nodeName; 
     logger.error(message, e); 
     throw new StartException(message, e); 
    } 

    /** 
    * Container life cycle call when activated 
    */ 
    @Override 
    public final void stop(StopContext context) { 
     if (deployDelayThread != null) { 
      deployDelayThread.shutdownNow(); 
     } 
     if (!started.compareAndSet(true, false) || bean == null) { 
      logger.warn("The service '" + this.getClass().getName() + "' is not active!"); 
     } else { 
      try { 
       InitialContext ic = new InitialContext(); 
       bean = (JmxMBean) ic.lookup(getJndiName()); 
       bean.stopHaSingleton(); 
       logger.info("*** Master Only: HASingleton service " + getJndiName() + " stopped on master:" + nodeName); 
      } catch (EJBException e) { 
       // Note: all these exceptions are already logged by JBoss 
      } catch (NamingException e) { 
       logger.error("Could not stop HASingleton service " + getJndiName() + " on " + nodeName, e); 
      } 
      logger.info("MASTER ONLY HASingleton service '" + this.getClass().getName() + "' Stopped on node " + nodeName); 
     } 
    } 

    private String getJndiName() { 
     return "java.global/path/to/your/singleton/ejb"; 
    } 
} 

最后列出您激活您的EJB全权负责META-INF/servcie/org.jboss.msc.service.ServiceActivator

com.mycompany.singletons.SingletonActivator 

您可能还需要依赖关系添加到清单META-INF/MANIFEST.MF文件JAR文件中,如下所示:Dependencies: org.jboss.msc, org.jboss.as.clustering.singleton, org.jboss.as.server

有可从红帽更广泛的实施指南在https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Development_Guide/Implement_an_HA_Singleton.html。您可能需要创建一个Redhat帐户才能访问此帐户。在JBoss发行版中也有一个快速启动的例子。

+0

谢谢你的回应。我正在使用Service Activator和一个类来查找EJB。另外,我正在使用standalone-full-ha.xml的修改版本。我正在修改我的代码,以便将两个战争打包成一个耳朵。 – Matt