3.2.8.2. 实现 HA 单点登录


总结

下面的过程演示了如何部署用 SingletonService decorator 包裹并用作群集内的单点登录服务的 Service。这个服务激活了群集里只启动一次的定时器。

过程 3.21. 实现 HA 单点登录服务

  1. 编写 HA 单点登录服务应用程序。

    下面是一个将部署为单点登录服务的用 SingletonService decorator 包裹的 Service 的简单例子。完整的例子请参考 JBoss EAP 6 附带的 cluster-ha-singleton quickstart。这个 Quickstart 包含构建和部署应用程序的所有说明。
    1. 创建服务。

      下面是一个服务的示例:
      package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;
      
      import java.util.Date;
      import java.util.concurrent.atomic.AtomicBoolean;
      
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      
      import org.jboss.logging.Logger;
      import org.jboss.msc.service.Service;
      import org.jboss.msc.service.ServiceName;
      import org.jboss.msc.service.StartContext;
      import org.jboss.msc.service.StartException;
      import org.jboss.msc.service.StopContext;
      
      
      /**
       * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
       */
      public class HATimerService implements Service<String> {
          private static final Logger LOGGER = Logger.getLogger(HATimerService.class);
          public static final ServiceName SINGLETON_SERVICE_NAME = ServiceName.JBOSS.append("quickstart", "ha", "singleton", "timer");
      
          /**
           * A flag whether the service is started.
           */
          private final AtomicBoolean started = new AtomicBoolean(false);
      
          /**
           * @return the name of the server node
           */
          public String getValue() throws IllegalStateException, IllegalArgumentException {
              LOGGER.infof("%s is %s at %s", HATimerService.class.getSimpleName(), (started.get() ? "started" : "not started"), System.getProperty("jboss.node.name"));
              return "";
          }
      
          public void start(StartContext arg0) throws StartException {
              if (!started.compareAndSet(false, true)) {
                  throw new StartException("The service is still started!");
              }
              LOGGER.info("Start HASingleton timer service '" + this.getClass().getName() + "'");
      
              final String node = System.getProperty("jboss.node.name");
              try {
                  InitialContext ic = new InitialContext();
                  ((Scheduler) ic.lookup("global/jboss-cluster-ha-singleton-service/SchedulerBean!org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.Scheduler")).initialize("HASingleton timer @" + node + " " + new Date());
              } catch (NamingException e) {
                  throw new StartException("Could not initialize timer", e);
              }
          }
      
          public void stop(StopContext arg0) {
              if (!started.compareAndSet(true, false)) {
                  LOGGER.warn("The service '" + this.getClass().getName() + "' is not active!");
              } else {
                  LOGGER.info("Stop HASingleton timer service '" + this.getClass().getName() + "'");
                  try {
                      InitialContext ic = new InitialContext();
                      ((Scheduler) ic.lookup("global/jboss-cluster-ha-singleton-service/SchedulerBean!org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.Scheduler")).stop();
                  } catch (NamingException e) {
                      LOGGER.error("Could not stop timer", e);
                  }
              }
          }
      }
      
      
      Copy to Clipboard Toggle word wrap
    2. 创建一个将 Service 安装为群集单点登录服务的激活器。

      下面的列表是一个服务激活器的例子,它将 HATimerService 安装为群集单点登录服务:
      package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;
      
      import org.jboss.as.clustering.singleton.SingletonService;
      import org.jboss.logging.Logger;
      import org.jboss.msc.service.DelegatingServiceContainer;
      import org.jboss.msc.service.ServiceActivator;
      import org.jboss.msc.service.ServiceActivatorContext;
      import org.jboss.msc.service.ServiceController;
      
      
      /**
       * Service activator that installs the HATimerService as a clustered singleton service
       * during deployment.
       *
       * @author Paul Ferraro
       */
      public class HATimerServiceActivator implements ServiceActivator {
          private final Logger log = Logger.getLogger(this.getClass());
      
          @Override
          public void activate(ServiceActivatorContext context) {
              log.info("HATimerService will be installed!");
      
              HATimerService service = new HATimerService();
              SingletonService<String> singleton = new SingletonService<String>(service, HATimerService.SINGLETON_SERVICE_NAME);
              /*
               * To pass a chain of election policies to the singleton, for example, 
               * to tell JGroups to prefer running the singleton on a node with a
               * particular name, uncomment the following line:
               */
              // singleton.setElectionPolicy(new PreferredSingletonElectionPolicy(new SimpleSingletonElectionPolicy(), new NamePreference("node2/cluster")));
      
              singleton.build(new DelegatingServiceContainer(context.getServiceTarget(), context.getServiceRegistry()))
                      .setInitialMode(ServiceController.Mode.ACTIVE)
                      .install()
              ;
          }
      }
      
      
      Copy to Clipboard Toggle word wrap

      注意

      上面的代码示例使用了 org.jboss.as.clustering.singleton.SingletonService 类,它是 JBoss EAP 私有 API 的一部分。JBoss EAP 7 里将有可用的公共 API,私有 API 会被废弃,但在 EAP 6.x 发行周期里我们仍将维护这个类。
    3. 创建 ServiceActivator 文件

      在应用程序的 resources/META-INF/services/ 目录里创建一个名为 org.jboss.msc.service.ServiceActivator 的文件。请添加包含之前步骤里创建的 ServiceActivator 类的全限定名称的一行内容。
      org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.HATimerServiceActivator 
      Copy to Clipboard Toggle word wrap
    4. 创建一个 Singleton bean,它实现了用作群集内 Singleton Timer 的 Timer。

      这个 Singleton bean 不能有 remote 接口,而且您不能从任何应用程序里的其他 EJB 引用其 local 接口。这阻止了客户或其他组件的查找,从而确保 SingletonService 可以完全控制单点登录。
      1. 创建 Scheduler 接口

        package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;
        
        /**
         * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
         */
        public interface Scheduler {
        
            void initialize(String info);
        
            void stop();
        
        } 
        
        
        Copy to Clipboard Toggle word wrap
      2. 创建实现群集内 Singleton Timer 的 Singleton bean。

        package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;
        
        import javax.annotation.Resource;
        import javax.ejb.ScheduleExpression;
        import javax.ejb.Singleton;
        import javax.ejb.Timeout;
        import javax.ejb.Timer;
        import javax.ejb.TimerConfig;
        import javax.ejb.TimerService;
        
        import org.jboss.logging.Logger;
        
        
        /**
         * A simple example to demonstrate a implementation of a cluster-wide singleton timer.
         *
         * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
         */
        @Singleton
        public class SchedulerBean implements Scheduler {
            private static Logger LOGGER = Logger.getLogger(SchedulerBean.class);
            @Resource
            private TimerService timerService;
        
            @Timeout
            public void scheduler(Timer timer) {
                LOGGER.info("HASingletonTimer: Info=" + timer.getInfo());
            }
        
            @Override
            public void initialize(String info) {
                ScheduleExpression sexpr = new ScheduleExpression();
                // set schedule to every 10 seconds for demonstration
                sexpr.hour("*").minute("*").second("0/10");
                // persistent must be false because the timer is started by the HASingleton service
                timerService.createCalendarTimer(sexpr, new TimerConfig(info, false));
            }
        
            @Override
            public void stop() {
                LOGGER.info("Stop all existing HASingleton timers");
                for (Timer timer : timerService.getTimers()) {
                    LOGGER.trace("Stop HASingleton timer: " + timer.getInfo());
                    timer.cancel();
                }
            }
        }
        
        
        Copy to Clipboard Toggle word wrap
  2. 启动每个启用了群集的 JBoss EAP 6 实例。

    要为独立服务器启用群集,您必须用 HA 配置集启动每个服务器并对每个实例使用唯一的节点名称和端口偏移量。
    • 对于 Linux,请使用下列命令行语法启动服务器:
      EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.node.name=UNIQUE_NODE_NAME -Djboss.socket.binding.port-offset=PORT_OFFSET
      Copy to Clipboard Toggle word wrap

      例 3.3. 在 Linux 上启动多个独立服务器实例

      $ EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.node.name=node1
      $ EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.node.name=node2 -Djboss.socket.binding.port-offset=100
      Copy to Clipboard Toggle word wrap
    • 对于 Microsoft Windows,请使用下列命令行语法启动服务器:
      EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.node.name=UNIQUE_NODE_NAME -Djboss.socket.binding.port-offset=PORT_OFFSET
      Copy to Clipboard Toggle word wrap

      例 3.4. 在 Microsoft Windows 上启动多个独立服务器实例

      C:> EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.node.name=node1
      C:> EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.node.name=node2 -Djboss.socket.binding.port-offset=100
      Copy to Clipboard Toggle word wrap

    注意

    如果您不想使用命令行参数,您可以为每个服务器实例配置 standalone-ha.xml 文件以绑定到单独的接口上。
  3. 将应用程序部署到服务器上

    下面的 Maven 命令部署应用程序到运行在默认端口的独立服务器上。
    mvn clean install jboss-as:deploy
    Copy to Clipboard Toggle word wrap
    要部署到其他的服务器,请传入服务器名称。如果位于不同的主机,在命令行上要指定主机名和端口号码:
    mvn clean package jboss-as:deploy -Djboss-as.hostname=localhost -Djboss-as.port=10099
    Copy to Clipboard Toggle word wrap
    设置 JBoss EAP 6 附带的 cluster-ha-singleton quickstart 的 Maven 配置和部署细节。
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2026 Red Hat
返回顶部