Quartz Job Scheduler - 多租户设置 [英] Quartz Job Scheduler - Multi-Tenant Setup

查看:111
本文介绍了Quartz Job Scheduler - 多租户设置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于我没有找到任何相关的东西来激发我的灵感,所以我想我会在这里想出这个.

Since I haven't found anything related to that which would have lead me to inspiration, I thought I'd come up with this here.

我最近使用 Quartz Job Scheduler 进行了很多工作已经在一个 RESTful Java Servlet 中实现,该 Servlet 应该为创建作业提供基于 Sencha ExtJS 的 UI.我们将 Authenticator 类与 DatabaseManager 结合使用,该类负责对用户和所有其他特定于数据库的内容进行身份验证(使用 Hibernate).

I recently worked a lot with the Quartz Job Scheduler which I've already implemented within a RESTful Java Servlet that is supposed to offer a Sencha ExtJS-based UI for job creation. We use an Authenticator class in combination with a DatabaseManager that take care of authenticating users and all other database-specific stuff (using Hibernate).

由于我们想在我们开发的 Java 企业应用程序中使用它,我们需要为每个客户运行这个东西.我们还要求将 JobStoreTX 用于 MySQL 数据库上的持久数据(显然是用于集群),因此 volatile RAMJobStore 实现是一个禁忌.我知道官方文档,并且 Quartz 本身似乎不支持多租户实现(请参阅 Quartz 集群).

Since we want to use it within the Java enterprise applications we develop, we need to run this thing for every customer. We also require the use of JobStoreTX for persistent data on MySQL databases (obviously for clustering), so volatile RAMJobStore implementation is a taboo. I am aware of the official documentation and that Quartz itself doesn't seem to support multi-tenant implementation (see Quartz Clustering).

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

Our setup looks kinda like this (simplfied):
- 1+ production Tomcat (serving application logic)
- 1+ production Apache (serving ExtJS front-end and static content)
- n databases (one for each customer)

添加一些更棘手的东西:
我们有客户特定的遗留模块(每个客户都有自己的应用程序托管),而更多最新的模块集中托管,并提供与客户相关的访问权限.

To add something even more tricky:
we have legacy modules that are customer-specific (each customer gets his own application hosting), while more up-to-date modules are hosted centralized with customer-related access.

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

In my opinion, it wouldn't be sufficient to created the Quartz-related tables on every customer database, since we want to stick with an easy, straight forward setup (which means e.g. same table prefix for each customer etc) just to not complicate the deployment of Quartz throughout the farm.

我已经考虑过将它与 MariaDB MaxScale 结合使用,并使用 filters 根据 RegEx 或类似的东西将 Quartz 路由到每个客户数据库,Quartz 只与 MaxScale 对话代理,但这对于我试图实现的目标来说似乎有点太多的开销,我什至不确定这是否会起作用.

I already thought about combining it with MariaDB MaxScale and using filters to route Quartz to each customer database based on RegEx or something similar, with Quartz only talking to the MaxScale proxy, but this seemed a little bit too much overhead for what I try to achieve and I am not even sure if this would work at all.

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

Is there something that would give me multi-tenancy with Quartz? Could you suggest an approach that would make Quartz being able to handle this, since we need to run jobs for each customer, but on "one" Tomcat (which is actually clustered and loadbalanced)? Or is there another product/framework/library that supports multi-tenancy out of the box?

非常感谢任何线索、想法或帮助!

Any lead, idea or help is very much appreciated!

推荐答案

你可以使用一个叫做 JobDataMap 这只是地图,您可以将其用作每个作业的数据容器.您需要做的是:

you can use something called JobDataMap which is just map which you can use as your data container for each job.. What you have to do is:

  • 创建新作业时,添加一些租户标识符
  • 创建 globalJobListener,您可以在其中将该映射中的租户标识符注入到您的 tenantContext
  • When creating new job, add some tenant identifier
  • Create globalJobListener where you can inject tenant identifier from that map to you tenantContext

这是我的代码:

// 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 Job Scheduler - 多租户设置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆