8.12. jakarta Enterprise Beans-clustered 数据库计时器


JBoss EAP 支持群集数据库支持定时器,用于在群集环境中持久保留 Jakarta Enterprise Beans 计时器。因为集群是通过数据库提供的,如果计时器在较短的时间内停机的数量增加,则性能会降低。您可以使用 ejb3/service=timer -service/database -data-store 组件的 refresh-interval 和 allow- execution 属性来优化性能。

您还可以在非集群模式下使用数据库计时器,如下所示:

  • refresh-interval 设置为 0
  • 为每个节点提供唯一的分区名称,或者对每个节点使用不同的数据库。

Jakarta Enterprise Beans-clustered 数据库计时器如下:

  • 允许执行计时器的每个节点都会为每个计时器调度一个超时时间。
  • 当这个超时过期时,每个节点都会尝试通过将其状态更新为 running 来锁定计时器。

    更新其状态的查询类似以下查询:

    UPDATE JBOSS_EJB_TIMER SET TIMER_STATE=? WHERE ID=? AND TIMER_STATE<>? AND NEXT_DATE=?;
    Copy to Clipboard Toggle word wrap

由于使用了事务处理和 READ_COMMITTED 或 SERIALIZABLE 隔离模式,只有一个节点成功更新该行,这是计时器执行的节点。

8.12.1. 设置 Jakarta Enterpise Beans-clustered 计时器

您可以通过添加数据库支持的计时器存储来设置 Jakarta Enterprise Beans-clustered 计时器。

先决条件

  • 数据库必须支持 READ_COMMITTED 或 SERIALIZABLE 隔离模式。

流程

  • 创建数据库支持的计时器存储:

    /subsystem=ejb3/service=timer-service/database-data-store=my-clustered-store:add(allow-execution=true, datasource-jndi-name="java:/MyDatasource", refresh-interval=60000, database="postgresql", partition="mypartition")
    Copy to Clipboard Toggle word wrap

    根据以下内容设置参数:

    • allow-execution : 设置为 true,以允许此节点执行计时器。如果将它设置为 false,JBoss EAP 会将此节点上的计时器添加到数据库,供另一个节点执行。当您将定时器执行限制为集群中几个节点时,可以减少总体数据库负载。
    • datasource-jndi-name :要使用的数据源。
    • refresh-interval :在此节点检查数据库是否由其他节点添加的新计时器前,设置必须调整的时间间隔。该值以毫秒为单位。

      重要

      设置较小的值意味着 JBoss EAP 加快使用定时器,但会增加数据库的负载。如果添加计时器的节点因为失败或 allow-execution 为 false,则此计时器可能无法运行,直到节点刷新后为止。

    • Database :定义正在使用的数据库的类型。些 SQL 语句由数据库自定义。

      如果未定义此属性,服务器将尝试自动检测该类型。目前支持的类型有 postgresql、mysqla cle、db2hsqlh2

      SQL 存在于以下文件中:module /system/layers/base/org/jboss/as/ejb3/main/timers/timer-sql.properties

      您可以通过向此文件中添加新的数据库特定 SQL 语句来修改已执行的 SQL 或添加对新数据库的支持。

    • 分区 :将值设置为您希望此节点所属的分区的名称。只有同一分区的节点的计时器才对此节点可见。使用此属性将大型集群分成几个较小的集群,以提高性能。
注意

要将此数据库数据存储用于非集群计时器,请将 refresh-interval 设置为零,并确保每个节点都有唯一的分区名称,或者对每个节点使用不同的数据库。

您可以使用单个数据存储作为所有应用程序的默认数据存储,或者为每个应用程序使用特定的数据存储。

先决条件

  • 您已设置了 Jakarta Enterprise Beans-clustered 数据库支持的定时器存储。

流程

  • 要将单个数据存储用作所有应用程序的默认值,请按如下所示更新 ejb3 子系统中的 default-data- 存储

    <timer-service thread-pool-name="timer" default-data-store="clustered-store">
        <data-stores>
            <database-data-store name="clustered-store" datasource-jndi-name="java:jboss/datasources/ExampleDS" partition="timer"/>
        </data-stores>
    </timer-service>
    Copy to Clipboard Toggle word wrap
  • 要将单独的数据存储用于特定应用程序,请在 jboss-ejb3.xml 文件中设置定时器数据存储名称:

    <?xml version="1.1" encoding="UTF-8"?>
    <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:timer="urn:timer-service:1.0" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0">
        <assembly-descriptor>
            <timer:timer>
                <ejb-name>*</ejb-name>
                <timer:persistence-store-name>my-clustered-store</timer:persistence-store-name>
            </timer:timer>
        </assembly-descriptor>
    </jboss:ejb-jar>
    Copy to Clipboard Toggle word wrap

您可以通过对业务方法配置 Jakarta Interceptors 以编程方式刷新计时器,从而强制计时器在 刷新过期前进行 刷新。

注意

在集群部署中,如果多个节点在较短的时间内更新其数据存储,内存中计时器状态可能会临时变得不同步。

先决条件

  • 您已配置了数据库支持的集群 Jakarta Enterprise Beans。

流程

  1. 实施 Jakarta Interceptors,使 wildfly.ejb.timer.refresh.enabled 设为 true

    import javax.interceptor.AroundInvoke;
    import javax.interceptor.Interceptor;
    import javax.interceptor.InvocationContext;
    
    /**
     * An interceptor to enable programmatic timer refresh across multiple nodes.
     */
    @Interceptor
    public class RefreshInterceptor {
        @AroundInvoke
        public Object intercept(InvocationContext context) throws Exception {
            context.getContextData().put("wildfly.ejb.timer.refresh.enabled", Boolean.TRUE);
            return context.proceed();
        }
    }
    Copy to Clipboard Toggle word wrap
  2. 配置 Jakarta Interceptors。

    • 您可以将 Jakarta Interceptors 配置为目标无状态或单例 bean 商业方法。当 wildfly.ejb.timer.refresh.enabled 设为 true 时,调用 TimerService.getAllTimers() 会在返回计时器前刷新计时器数据存储。

      @Singleton
      public class RefreshBean1 ... {
      
          @Interceptors(RefreshInterceptor.class)
          public void businessMethod1() {
              ...
              // since wildfly.ejb.timer.refresh.enabled is set to true in interceptor for this business method,
              // calling timerService.getAllTimers() will first refresh from timer datastore before returning timers.
              final Collection<Timer> allTimers = timerService.getAllTimers();
              ...
          }
      }
      Copy to Clipboard Toggle word wrap
    • 或者,您也可以实施一种专用的业务方法,以便在需要时以编程方式刷新应用的其他部分调用的计时器。

          @Interceptors(RefreshInterceptor.class)
          public List<Timer> getAllTimerInfoWithRefresh() {
              return timerService.getAllTimers();
          }
      
          public void businessMethod1() {
              final LocalBusinessInterface businessObject = sessionContext.getBusinessObject(LocalBusinessInterface.class);
              businessObject.getAllTimerInfoWithRefresh();
      
              // timer has been programmatically refreshed from datastore.
              // continue with other business logic...
          }
      Copy to Clipboard Toggle word wrap
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

Theme

© 2025 Red Hat