Tomcat Quartz作业计划程序-多租户设置

Tomcat Quartz作业计划程序-多租户设置,tomcat,jakarta-ee,quartz-scheduler,mariadb,multi-tenant,Tomcat,Jakarta Ee,Quartz Scheduler,Mariadb,Multi Tenant,因为我还没有找到任何能让我获得灵感的东西,所以我想我会在这里提出这个 我最近做了很多工作,我已经在一个RESTfulJavaservlet中实现了这些工作,该Servlet应该提供一个基于SenchaExtJS的UI来创造就业机会。我们将Authenticator类与DatabaseManager结合使用,后者负责验证用户和所有其他特定于数据库的内容(使用Hibernate) 因为我们希望在我们开发的Java企业应用程序中使用它,所以我们需要为每个客户运行它。对于MySQL数据库上的持久数据,我

因为我还没有找到任何能让我获得灵感的东西,所以我想我会在这里提出这个

我最近做了很多工作,我已经在一个RESTfulJavaservlet中实现了这些工作,该Servlet应该提供一个基于SenchaExtJS的UI来创造就业机会。我们将Authenticator类与DatabaseManager结合使用,后者负责验证用户和所有其他特定于数据库的内容(使用Hibernate)

因为我们希望在我们开发的Java企业应用程序中使用它,所以我们需要为每个客户运行它。对于MySQL数据库上的持久数据,我们还需要使用JobStoreTX(显然是为了集群),因此不允许使用易失性的RAMJobStore实现。我知道官方文档,Quartz本身似乎不支持多租户实现(请参阅)

我们的设置看起来有点像这样(简化):
-1+生产Tomcat(服务应用程序逻辑)
-1+生产Apache(提供ExtJS前端和静态内容)
-n个数据库(每个客户一个)

要添加更棘手的内容:
我们有特定于客户的遗留模块(每个客户都有自己的应用程序托管),而更多的最新模块集中托管,并具有与客户相关的访问权限

在我看来,在每个客户数据库上创建与Quartz相关的表是不够的,因为我们希望坚持简单、直接的设置(这意味着每个客户都有相同的表前缀等),只是为了不使整个服务器场中Quartz的部署复杂化

我已经考虑过将其与MariaDB MaxScale相结合,并使用过滤器将Quartz路由到基于RegEx或类似内容的每个客户数据库,Quartz只与MaxScale代理进行对话,但对于我试图实现的目标来说,这似乎有点太高了,我甚至不确定这是否可行

是否有什么东西可以让我与Quartz实现多租户?您能否建议一种方法,使Quartz能够处理这个问题,因为我们需要为每个客户运行作业,但要在“一个”Tomcat上运行(实际上是集群和负载平衡的)?或者是否有其他产品/框架/库支持开箱即用的多租户


非常感谢您的任何指导、想法或帮助

我终于让它写入多个数据库


我所做的是根据各自的客户参数为每个客户动态生成Quartz属性文件,并使程序逻辑读取这个新生成的文件。最后,每个客户都有自己的Quartz作业存储到自己的数据库中。

您可以使用一种称为的东西,它只是映射您可以用作每个作业的数据容器的东西。。你要做的是:

  • 创建新作业时,添加一些租户标识符
  • 创建
    globalJobListener
    ,您可以将该映射中的租户标识符注入到您的租户上下文中
这是我的密码:

// quartz configuration with custom job listener
@Configuration
public class MultiTenantQuartzAutoConfiguration {

    @Bean
    public SchedulerFactoryBean schedulerFactory() {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(jobFactory());
        schedulerFactoryBean.setGlobalJobListeners(new MultiTenantQuartzJobListener());

        return schedulerFactoryBean;
    }

    @Bean
    public SpringBeanJobFactory jobFactory() {
        return new SpringBeanJobFactory();
    }
}

// custom job listener
public class MultiTenantQuartzJobListener implements JobListener {

    private static final String NAME = "tenantContext";

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        TenantContext.setTenantId(context.getJobDetail().getJobDataMap().getString(TenantContext.TENANT_HEADER));
    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        TenantContext.clear();
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        TenantContext.clear();
    }
}

// and here is how to create job with filled JobDataMap
Class c = Class.forName(jobInfo.getClassName());

JobDetail job = newJob(c)
        .withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup())
        .withDescription(jobInfo.getDesc())
        .usingJobData(TenantContext.TENANT_HEADER, TenantContext.getTenantId())
        .build();

CronTrigger trigger = newTrigger()
        .withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup())
        .withSchedule(cronSchedule(jobInfo.getCronExpression()))
        .build();

var ft = scheduler.scheduleJob(job, trigger);

我们目前只处于开发阶段,但目前我们选择在每个客户数据库上创建与石英相关的表。如果需要,您可以通过quartz属性文件更改quartz表的名称(这样每个客户的表前缀都相同),我想我找到了一个可以轻松应用于我们的软件架构的解决方案。因为每个客户都有自己的数据库,所以在整个应用程序逻辑中都有一个系统参数,对于每个客户都是唯一的。此参数将在创建时自动附加到作业和组名。通过这种方式,我们应该能够为所有客户在单个数据库上运行Quartz。到目前为止工作顺利。只是一个问题:在我设计的创建作业的界面(使用Sencha ExtJS)中,用户可以选择只创建一次或重复创建作业。当我创建一个一次性作业时,该作业(和触发器)在执行后不会保留在数据库中。有没有一种方法可以保存那些已经被触发的作业,而这些作业不会在数据库中重复出现?我认为如果不应该再发生任何此类事件,它将始终删除该作业。如果您想保存它以供用户重用,那么我们要做的是将调度数据保存在一个单独的表中。如果你想记录日志,可能会对你有用。修复了它。作业类有一个
@PersistJobDataAfterExecution
注释。无论如何,谢谢。在这个解决方案中,每个客户都有一个quartz调度程序,不是吗?因为我从未听说quartz支持多个数据源。谢谢你的回答。是的,那是正确的。虽然花了一些时间才弄清楚如何为每个租户动态创建配置。尽管如此,您仍然需要弄清楚是什么让租户“独一无二”。您好@MoshPit,您已经实现了它,这真是太棒了。我想知道,你们是如何实施的?请您详细解释一下,或者提供一些代码示例。这对我真的很有帮助。提前谢谢。