• 使用sqlserver搭建高可用双机热备的Quartz集群部署【附源码】


      一般拿Timer和Quartz相比较的,简直就是对Quartz的侮辱,两者的功能根本就不在一个层级上,如本篇介绍的Quartz强大的集群机制,可以采用基于

    sqlserver,mysql的集群方案,当然还可以在第三方插件的基础上实现quartz序列化到热炒的mongodb,redis,震撼力可想而知,接下来本篇就和大家聊

    一聊怎么搭建基于sqlserver的quartz集群,实现这么一种双机热备的强大功能。

    一:下载sqlserver版的建表脚本

        首先大家可以通过github上搜索quartz的源代码,在源码项目的/database/tables目录下,可以找到firebird,oracle,mysql,sqlserver等建库脚本,

    本篇只需拿取sqlserver版本即可。 https://github.com/quartznet/quartznet/tree/master/database/tables  如下图所示

       

         从上面的截图中可以看到,我接下来要做的事情就是增加一个你需要创建的database名字,这里取为:【quartz】,完整的脚本如下:

      1 -- this script is for SQL Server and Azure SQL
      2 
      3 CREATE DATABASE [quartz]
      4 GO
      5 
      6 USE [quartz]
      7 GO
      8 
      9 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
     10 ALTER TABLE [dbo].[QRTZ_TRIGGERS] DROP CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS
     11 GO
     12 
     13 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
     14 ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] DROP CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS
     15 GO
     16 
     17 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
     18 ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS
     19 GO
     20 
     21 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
     22 ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS
     23 GO
     24 
     25 IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]'))
     26 ALTER TABLE [dbo].[QRTZ_JOB_LISTENERS] DROP CONSTRAINT [FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]
     27 
     28 IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]'))
     29 ALTER TABLE [dbo].[QRTZ_TRIGGER_LISTENERS] DROP CONSTRAINT [FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]
     30 
     31 
     32 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CALENDARS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     33 DROP TABLE [dbo].[QRTZ_CALENDARS]
     34 GO
     35 
     36 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CRON_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     37 DROP TABLE [dbo].[QRTZ_CRON_TRIGGERS]
     38 GO
     39 
     40 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_BLOB_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     41 DROP TABLE [dbo].[QRTZ_BLOB_TRIGGERS]
     42 GO
     43 
     44 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_FIRED_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     45 DROP TABLE [dbo].[QRTZ_FIRED_TRIGGERS]
     46 GO
     47 
     48 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_PAUSED_TRIGGER_GRPS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     49 DROP TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS]
     50 GO
     51 
     52 IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]') AND type in (N'U'))
     53 DROP TABLE [dbo].[QRTZ_JOB_LISTENERS]
     54 
     55 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SCHEDULER_STATE]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     56 DROP TABLE [dbo].[QRTZ_SCHEDULER_STATE]
     57 GO
     58 
     59 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_LOCKS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     60 DROP TABLE [dbo].[QRTZ_LOCKS]
     61 GO
     62 IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]') AND type in (N'U'))
     63 DROP TABLE [dbo].[QRTZ_TRIGGER_LISTENERS]
     64 
     65 
     66 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     67 DROP TABLE [dbo].[QRTZ_JOB_DETAILS]
     68 GO
     69 
     70 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPLE_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     71 DROP TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS]
     72 GO
     73 
     74 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPROP_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     75 DROP TABLE [dbo].QRTZ_SIMPROP_TRIGGERS
     76 GO
     77 
     78 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
     79 DROP TABLE [dbo].[QRTZ_TRIGGERS]
     80 GO
     81 
     82 CREATE TABLE [dbo].[QRTZ_CALENDARS] (
     83   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
     84   [CALENDAR_NAME] [NVARCHAR] (200)  NOT NULL ,
     85   [CALENDAR] [IMAGE] NOT NULL
     86 )
     87 GO
     88 
     89 CREATE TABLE [dbo].[QRTZ_CRON_TRIGGERS] (
     90   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
     91   [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
     92   [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
     93   [CRON_EXPRESSION] [NVARCHAR] (120)  NOT NULL ,
     94   [TIME_ZONE_ID] [NVARCHAR] (80) 
     95 )
     96 GO
     97 
     98 CREATE TABLE [dbo].[QRTZ_FIRED_TRIGGERS] (
     99   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    100   [ENTRY_ID] [NVARCHAR] (140)  NOT NULL ,
    101   [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
    102   [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
    103   [INSTANCE_NAME] [NVARCHAR] (200)  NOT NULL ,
    104   [FIRED_TIME] [BIGINT] NOT NULL ,
    105   [SCHED_TIME] [BIGINT] NOT NULL ,
    106   [PRIORITY] [INTEGER] NOT NULL ,
    107   [STATE] [NVARCHAR] (16)  NOT NULL,
    108   [JOB_NAME] [NVARCHAR] (150)  NULL ,
    109   [JOB_GROUP] [NVARCHAR] (150)  NULL ,
    110   [IS_NONCONCURRENT] BIT  NULL ,
    111   [REQUESTS_RECOVERY] BIT  NULL 
    112 )
    113 GO
    114 
    115 CREATE TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] (
    116   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    117   [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL 
    118 )
    119 GO
    120 
    121 CREATE TABLE [dbo].[QRTZ_SCHEDULER_STATE] (
    122   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    123   [INSTANCE_NAME] [NVARCHAR] (200)  NOT NULL ,
    124   [LAST_CHECKIN_TIME] [BIGINT] NOT NULL ,
    125   [CHECKIN_INTERVAL] [BIGINT] NOT NULL
    126 )
    127 GO
    128 
    129 CREATE TABLE [dbo].[QRTZ_LOCKS] (
    130   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    131   [LOCK_NAME] [NVARCHAR] (40)  NOT NULL 
    132 )
    133 GO
    134 
    135 CREATE TABLE [dbo].[QRTZ_JOB_DETAILS] (
    136   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    137   [JOB_NAME] [NVARCHAR] (150)  NOT NULL ,
    138   [JOB_GROUP] [NVARCHAR] (150)  NOT NULL ,
    139   [DESCRIPTION] [NVARCHAR] (250) NULL ,
    140   [JOB_CLASS_NAME] [NVARCHAR] (250)  NOT NULL ,
    141   [IS_DURABLE] BIT  NOT NULL ,
    142   [IS_NONCONCURRENT] BIT  NOT NULL ,
    143   [IS_UPDATE_DATA] BIT  NOT NULL ,
    144   [REQUESTS_RECOVERY] BIT  NOT NULL ,
    145   [JOB_DATA] [IMAGE] NULL
    146 )
    147 GO
    148 
    149 CREATE TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] (
    150   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    151   [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
    152   [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
    153   [REPEAT_COUNT] [INTEGER] NOT NULL ,
    154   [REPEAT_INTERVAL] [BIGINT] NOT NULL ,
    155   [TIMES_TRIGGERED] [INTEGER] NOT NULL
    156 )
    157 GO
    158 
    159 CREATE TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] (
    160   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    161   [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
    162   [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
    163   [STR_PROP_1] [NVARCHAR] (512) NULL,
    164   [STR_PROP_2] [NVARCHAR] (512) NULL,
    165   [STR_PROP_3] [NVARCHAR] (512) NULL,
    166   [INT_PROP_1] [INT] NULL,
    167   [INT_PROP_2] [INT] NULL,
    168   [LONG_PROP_1] [BIGINT] NULL,
    169   [LONG_PROP_2] [BIGINT] NULL,
    170   [DEC_PROP_1] [NUMERIC] (13,4) NULL,
    171   [DEC_PROP_2] [NUMERIC] (13,4) NULL,
    172   [BOOL_PROP_1] BIT NULL,
    173   [BOOL_PROP_2] BIT NULL,
    174 )
    175 GO
    176 
    177 CREATE TABLE [dbo].[QRTZ_BLOB_TRIGGERS] (
    178   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    179   [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
    180   [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
    181   [BLOB_DATA] [IMAGE] NULL
    182 )
    183 GO
    184 
    185 CREATE TABLE [dbo].[QRTZ_TRIGGERS] (
    186   [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
    187   [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
    188   [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
    189   [JOB_NAME] [NVARCHAR] (150)  NOT NULL ,
    190   [JOB_GROUP] [NVARCHAR] (150)  NOT NULL ,
    191   [DESCRIPTION] [NVARCHAR] (250) NULL ,
    192   [NEXT_FIRE_TIME] [BIGINT] NULL ,
    193   [PREV_FIRE_TIME] [BIGINT] NULL ,
    194   [PRIORITY] [INTEGER] NULL ,
    195   [TRIGGER_STATE] [NVARCHAR] (16)  NOT NULL ,
    196   [TRIGGER_TYPE] [NVARCHAR] (8)  NOT NULL ,
    197   [START_TIME] [BIGINT] NOT NULL ,
    198   [END_TIME] [BIGINT] NULL ,
    199   [CALENDAR_NAME] [NVARCHAR] (200)  NULL ,
    200   [MISFIRE_INSTR] [INTEGER] NULL ,
    201   [JOB_DATA] [IMAGE] NULL
    202 )
    203 GO
    204 
    205 ALTER TABLE [dbo].[QRTZ_CALENDARS] WITH NOCHECK ADD
    206   CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY  CLUSTERED
    207   (
    208     [SCHED_NAME],
    209     [CALENDAR_NAME]
    210   ) 
    211 GO
    212 
    213 ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] WITH NOCHECK ADD
    214   CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY  CLUSTERED
    215   (
    216     [SCHED_NAME],
    217     [TRIGGER_NAME],
    218     [TRIGGER_GROUP]
    219   ) 
    220 GO
    221 
    222 ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] WITH NOCHECK ADD
    223   CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY  CLUSTERED
    224   (
    225     [SCHED_NAME],
    226     [ENTRY_ID]
    227   ) 
    228 GO
    229 
    230 ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
    231   CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY  CLUSTERED
    232   (
    233     [SCHED_NAME],
    234     [TRIGGER_GROUP]
    235   ) 
    236 GO
    237 
    238 ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] WITH NOCHECK ADD
    239   CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY  CLUSTERED
    240   (
    241     [SCHED_NAME],
    242     [INSTANCE_NAME]
    243   ) 
    244 GO
    245 
    246 ALTER TABLE [dbo].[QRTZ_LOCKS] WITH NOCHECK ADD
    247   CONSTRAINT [PK_QRTZ_LOCKS] PRIMARY KEY  CLUSTERED
    248   (
    249     [SCHED_NAME],
    250     [LOCK_NAME]
    251   ) 
    252 GO
    253 
    254 ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] WITH NOCHECK ADD
    255   CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY  CLUSTERED
    256   (
    257     [SCHED_NAME],
    258     [JOB_NAME],
    259     [JOB_GROUP]
    260   ) 
    261 GO
    262 
    263 ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] WITH NOCHECK ADD
    264   CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY  CLUSTERED
    265   (
    266     [SCHED_NAME],
    267     [TRIGGER_NAME],
    268     [TRIGGER_GROUP]
    269   ) 
    270 GO
    271 
    272 ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] WITH NOCHECK ADD
    273   CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY  CLUSTERED
    274   (
    275     [SCHED_NAME],
    276     [TRIGGER_NAME],
    277     [TRIGGER_GROUP]
    278   ) 
    279 GO
    280 
    281 ALTER TABLE [dbo].[QRTZ_TRIGGERS] WITH NOCHECK ADD
    282   CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY  CLUSTERED
    283   (
    284     [SCHED_NAME],
    285     [TRIGGER_NAME],
    286     [TRIGGER_GROUP]
    287   ) 
    288 GO
    289 
    290 ALTER TABLE [dbo].QRTZ_BLOB_TRIGGERS WITH NOCHECK ADD
    291   CONSTRAINT [PK_QRTZ_BLOB_TRIGGERS] PRIMARY KEY  CLUSTERED
    292   (
    293     [SCHED_NAME],
    294     [TRIGGER_NAME],
    295     [TRIGGER_GROUP]
    296   ) 
    297 GO
    298 
    299 ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD
    300   CONSTRAINT [FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
    301   (
    302     [SCHED_NAME],
    303     [TRIGGER_NAME],
    304     [TRIGGER_GROUP]
    305   ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
    306     [SCHED_NAME],
    307     [TRIGGER_NAME],
    308     [TRIGGER_GROUP]
    309   ) ON DELETE CASCADE
    310 GO
    311 
    312 ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD
    313   CONSTRAINT [FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
    314   (
    315     [SCHED_NAME],
    316     [TRIGGER_NAME],
    317     [TRIGGER_GROUP]
    318   ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
    319     [SCHED_NAME],
    320     [TRIGGER_NAME],
    321     [TRIGGER_GROUP]
    322   ) ON DELETE CASCADE
    323 GO
    324 
    325 ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD
    326   CONSTRAINT [FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
    327   (
    328     [SCHED_NAME],
    329     [TRIGGER_NAME],
    330     [TRIGGER_GROUP]
    331   ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
    332     [SCHED_NAME],
    333     [TRIGGER_NAME],
    334     [TRIGGER_GROUP]
    335   ) ON DELETE CASCADE
    336 GO
    337 
    338 ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD
    339   CONSTRAINT [FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS] FOREIGN KEY
    340   (
    341     [SCHED_NAME],
    342     [JOB_NAME],
    343     [JOB_GROUP]
    344   ) REFERENCES [dbo].[QRTZ_JOB_DETAILS] (
    345     [SCHED_NAME],
    346     [JOB_NAME],
    347     [JOB_GROUP]
    348   )
    349 GO
    350 
    351 CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
    352 CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP)
    353 CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME)
    354 CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
    355 CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE)
    356 CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE)
    357 CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE)
    358 CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME)
    359 CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME)
    360 CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME)
    361 CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE)
    362 CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE)
    363 
    364 CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME)
    365 CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY)
    366 CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
    367 CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP)
    368 CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    369 CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
    370 GO
    View Code

    二:配置quartz的集群参数

        当我们写var scheduler = StdSchedulerFactory.GetDefaultScheduler()这段代码的时候,如果大家看过源码的话,会知道这个GetScheduler的

    过程中有一个初始化方法【Instantiate】方法,此方法中你会发现在做DBProvider的时候会需要几个参数来初始化DB的,比如下面看到的几个标红属性。

     1             IList<string> dsNames = cfg.GetPropertyGroups(PropertyDataSourcePrefix);
     2             foreach (string dataSourceName in dsNames)
     3             {
     4                 string datasourceKey = "{0}.{1}".FormatInvariant(PropertyDataSourcePrefix, dataSourceName);
     5                 NameValueCollection propertyGroup = cfg.GetPropertyGroup(datasourceKey, true);
     6                 PropertiesParser pp = new PropertiesParser(propertyGroup);
     7 
     8                 Type cpType = loadHelper.LoadType(pp.GetStringProperty(PropertyDbProviderType, null));
     9 
    10                 // custom connectionProvider...
    11                 if (cpType != null)
    12                 {
    13                     IDbProvider cp;
    14                     try
    15                     {
    16                         cp = ObjectUtils.InstantiateType<IDbProvider>(cpType);
    17                     }
    18                     catch (Exception e)
    19                     {
    20                         initException = new SchedulerException("ConnectionProvider of type '{0}' could not be instantiated.".FormatInvariant(cpType), e);
    21                         throw initException;
    22                     }
    23 
    24                     try
    25                     {
    26                         // remove the type name, so it isn't attempted to be set
    27                         pp.UnderlyingProperties.Remove(PropertyDbProviderType);
    28 
    29                         ObjectUtils.SetObjectProperties(cp, pp.UnderlyingProperties);
    30                         cp.Initialize();
    31                     }
    32                     catch (Exception e)
    33                     {
    34                         initException = new SchedulerException("ConnectionProvider type '{0}' props could not be configured.".FormatInvariant(cpType), e);
    35                         throw initException;
    36                     }
    37 
    38                     dbMgr = DBConnectionManager.Instance;
    39                     dbMgr.AddConnectionProvider(dataSourceName, cp);
    40                 }
    41                 else
    42                 {
    43                     string dsProvider = pp.GetStringProperty(PropertyDataSourceProvider, null);
    44                     string dsConnectionString = pp.GetStringProperty(PropertyDataSourceConnectionString, null);
    45                     string dsConnectionStringName = pp.GetStringProperty(PropertyDataSourceConnectionStringName, null);
    46 
    47                     if (dsConnectionString == null && !String.IsNullOrEmpty(dsConnectionStringName))
    48                     {
    49 
    50                         ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[dsConnectionStringName];
    51                         if (connectionStringSettings == null)
    52                         {
    53                             initException = new SchedulerException("Named connection string '{0}' not found for DataSource: {1}".FormatInvariant(dsConnectionStringName, dataSourceName));
    54                             throw initException;
    55                         }
    56                         dsConnectionString = connectionStringSettings.ConnectionString;
    57                     }
    58 
    59                     if (dsProvider == null)
    60                     {
    61                         initException = new SchedulerException("Provider not specified for DataSource: {0}".FormatInvariant(dataSourceName));
    62                         throw initException;
    63                     }
    64                     if (dsConnectionString == null)
    65                     {
    66                         initException = new SchedulerException("Connection string not specified for DataSource: {0}".FormatInvariant(dataSourceName));
    67                         throw initException;
    68                     }
    69                     try
    70                     {
    71                         DbProvider dbp = new DbProvider(dsProvider, dsConnectionString);
    72                         dbp.Initialize();
    73 
    74                         dbMgr = DBConnectionManager.Instance;
    75                         dbMgr.AddConnectionProvider(dataSourceName, dbp);
    76                     }
    77                     catch (Exception exception)
    78                     {
    79                         initException = new SchedulerException("Could not Initialize DataSource: {0}".FormatInvariant(dataSourceName), exception);
    80                         throw initException;
    81                     }
    82                 }
    83             }

         接下来的问题就是这几个属性是如何配置进去的,仔细观察上面代码,你会发现所有的配置的源头都来自于cfg变量,ok,接下来你可以继续翻看代码,相信

    你会看到有一个Initialize方法就是做cfg变量的初始化,如下代码所示:

     1   public void Initialize()
     2         {
     3             // short-circuit if already initialized
     4             if (cfg != null)
     5             {
     6                 return;
     7             }
     8             if (initException != null)
     9             {
    10                 throw initException;
    11             }
    12 
    13             NameValueCollection props = (NameValueCollection) ConfigurationManager.GetSection(ConfigurationSectionName);
    14 
    15             string requestedFile = QuartzEnvironment.GetEnvironmentVariable(PropertiesFile);
    16 
    17             string propFileName = requestedFile != null && requestedFile.Trim().Length > 0 ? requestedFile : "~/quartz.config";
    18 
    19             // check for specials
    20             try
    21             {
    22                 propFileName = FileUtil.ResolveFile(propFileName);
    23             }
    24             catch (SecurityException)
    25             {
    26                 log.WarnFormat("Unable to resolve file path '{0}' due to security exception, probably running under medium trust");
    27                 propFileName = "quartz.config";
    28             }
    29 
    30             if (props == null && File.Exists(propFileName))
    31             {
    32                 // file system
    33                 try
    34                 {
    35                     PropertiesParser pp = PropertiesParser.ReadFromFileResource(propFileName);
    36                     props = pp.UnderlyingProperties;
    37                     Log.Info(string.Format("Quartz.NET properties loaded from configuration file '{0}'", propFileName));
    38                 }
    39                 catch (Exception ex)
    40                 {
    41                     Log.Error("Could not load properties for Quartz from file {0}: {1}".FormatInvariant(propFileName, ex.Message), ex);
    42                 }
    43 
    44             }
    45             if (props == null)
    46             {
    47                 // read from assembly
    48                 try
    49                 {
    50                     PropertiesParser pp = PropertiesParser.ReadFromEmbeddedAssemblyResource("Quartz.quartz.config");
    51                     props = pp.UnderlyingProperties;
    52                     Log.Info("Default Quartz.NET properties loaded from embedded resource file");
    53                 }
    54                 catch (Exception ex)
    55                 {
    56                     Log.Error("Could not load default properties for Quartz from Quartz assembly: {0}".FormatInvariant(ex.Message), ex);
    57                 }
    58             }
    59             if (props == null)
    60             {
    61                 throw new SchedulerConfigException(
    62                     @"Could not find <quartz> configuration section from your application config or load default configuration from assembly.
    63 Please add configuration to your application config file to correctly initialize Quartz.");
    64             }
    65             Initialize(OverrideWithSysProps(props));
    66         }

         

         仔细阅读上面的一串代码,你会发现,默认quartz参数配置来源于三个地方。

    1. app.config中的section节点。

    2. bin目录下的~/quartz.config文件。

    3. 默认配置的NameValueCollection字典集合,也就是上一篇博客给大家做的一个演示。

       

         我个人不怎么喜欢通过quartz.config文件进行配置,这样也容易写死,所以我还是喜欢使用最简单的NameValueCollection配置,因为它的数据源可来源

    于第三方存储结构中,配置代码如下:

     1                 //1.首先创建一个作业调度池
     2                 var properties = new NameValueCollection();
     3                 //存储类型
     4                 properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
     5 
     6                 //驱动类型
     7                 properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";                //数据源名称
     8                 properties["quartz.jobStore.dataSource"] = "myDS";
     9 
    10                 //连接字符串
    11                 properties["quartz.dataSource.myDS.connectionString"] = @"server=.;Initial Catalog=quartz;Integrated Security=True";
    12                 //sqlserver版本
    13                 properties["quartz.dataSource.myDS.provider"] = "SqlServer-20";
    14 
    15                 //是否集群
    16                 properties["quartz.jobStore.clustered"] = "true";
    17                 properties["quartz.scheduler.instanceId"] = "AUTO";

        上面的代码配置我都加过详细的注释,大家应该都能看得懂,而且这些配置就是这么定死的,没什么修改的空间,大家记住即可。

    三:Job和Trigger定义

         在集群中环境下,job和trigger的定义该怎么写的?大家也不要想的太复杂,注意一点就可以了,在Schedule一个Job时候,通过CheckExists判断一下

    这个Job在Scheduler中是否已经存在了,如果存在,你就不能再次通过Schedule去重复调度一个Job就可以了。。。所以判断的代码也很简单,如下所示:

     1          IScheduler scheduler = factory.GetScheduler();
     2 
     3                 scheduler.Start();
     4 
     5                 var jobKey = JobKey.Create("myjob", "group");
     6 
     7                 if (scheduler.CheckExists(jobKey))
     8                 {
     9                     Console.WriteLine("当前job已经存在,无需调度:{0}", jobKey.ToString());
    10                 }
    11                 else
    12                 {
    13                     IJobDetail job = JobBuilder.Create<HelloJob>()
    14                            .WithDescription("使用quartz进行持久化存储")
    15                            .StoreDurably()
    16                            .RequestRecovery()
    17                            .WithIdentity(jobKey)
    18                            .UsingJobData("count", 1)
    19                            .Build();
    20 
    21                     ITrigger trigger = TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInSeconds(2).RepeatForever())
    22                                                               .Build();
    23 
    24                     scheduler.ScheduleJob(job, trigger);
    25 
    26                     Console.WriteLine("调度进行中!!!");
    27                 }

    上面这段代码,大家就可以部署在多台机器中了,是不是很简单?

    四:强大的cluster完整演示

       

         所有的初始化工作都做完了,接下来我们copy一份bin文件,同时打开两个console程序,如下所示,可以看到job任务只会被一个console调度,另外

    一个在空等待。

           然后你肯定很好奇的跑到sqlserver中去看看,是否已经有job和trigger的db存储,很开心吧,数据都有的。。。

           好了,一切都是那么完美,接下来可以展示一下quartz集群下的高可用啦,如果某一个console挂了,那么另一台console会把这个任务给接过来,实

    现强大的高可用。。。所以我要做的事情就是把console1关掉,再看看console2是不是可以开始调度job了???

    完美,这个就是本篇给大家介绍的Quartz的Cluster集群,一台挂,另一台顶住,双机热备,当然这些console你可以部署在多台机器中,要做的就是保持各

    个server的时间同步,因为quarz是依赖于本机server的时间,好了,本篇就先说到这里吧。

    小礼物走一波,双击666。。。  完整代码:SimpleSchedulerApp.zip

  • 相关阅读:
    排序算法研究
    SqlParameters参数
    winfrom项目
    方法参数中有out和in关键字是什么意思?
    在C#中使用存储过程
    11Book系列多表群操作
    7drf过滤排序分页异常处理
    12RBAC基于角色的访问控制
    5drf路由组件
    8drf自动生成接口文档
  • 原文地址:https://www.cnblogs.com/huangxincheng/p/6916246.html
Copyright © 2020-2023  润新知