一般拿Timer和Quartz相比較的,簡(jiǎn)直就是對(duì)Quartz的侮辱,兩者的功能根本就不在一個(gè)層級(jí)上,如本篇介紹的Quartz強(qiáng)大的集群機(jī)制,可以采用基于
sqlserver,mysql的集群方案,當(dāng)然還可以在第三方插件的基礎(chǔ)上實(shí)現(xiàn)quartz序列化到熱炒的mongodb,redis,震撼力可想而知,接下來(lái)本篇就和大家聊
一聊怎么搭建基于sqlserver的quartz集群,實(shí)現(xiàn)這么一種雙機(jī)熱備的強(qiáng)大功能。
一:下載sqlserver版的建表腳本
首先大家可以通過(guò)github上搜索quartz的源代碼,在源碼項(xiàng)目的/database/tables目錄下,可以找到firebird,oracle,mysql,sqlserver等建庫(kù)腳本,
本篇只需拿取sqlserver版本即可。 https://github.com/quartznet/quartznet/tree/master/database/tables 如下圖所示
從上面的截圖中可以看到,我接下來(lái)要做的事情就是增加一個(gè)你需要?jiǎng)?chuàng)建的database名字,這里取為:【quartz】,完整的腳本如下:
View Code
二:配置quartz的集群參數(shù)
當(dāng)我們寫var scheduler = StdSchedulerFactory.GetDefaultScheduler()這段代碼的時(shí)候,如果大家看過(guò)源碼的話,會(huì)知道這個(gè)GetScheduler的
過(guò)程中有一個(gè)初始化方法【Instantiate】方法,此方法中你會(huì)發(fā)現(xiàn)在做DBProvider的時(shí)候會(huì)需要幾個(gè)參數(shù)來(lái)初始化DB的,比如下面看到的幾個(gè)標(biāo)紅屬性。
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 try15 {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 try25 {26 // remove the type name, so it isn't attempted to be set27 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 else42 {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 try70 {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 }
接下來(lái)的問(wèn)題就是這幾個(gè)屬性是如何配置進(jìn)去的,仔細(xì)觀察上面代碼,你會(huì)發(fā)現(xiàn)所有的配置的源頭都來(lái)自于cfg變量,ok,接下來(lái)你可以繼續(xù)翻看代碼,相信
你會(huì)看到有一個(gè)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 specials20 try21 {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 system33 try34 {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 assembly48 try49 {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 }
仔細(xì)閱讀上面的一串代碼,你會(huì)發(fā)現(xiàn),默認(rèn)quartz參數(shù)配置來(lái)源于三個(gè)地方。
1. app.config中的section節(jié)點(diǎn)。
2. bin目錄下的~/quartz.config文件。
3. 默認(rèn)配置的NameValueCollection字典集合,也就是上一篇博客給大家做的一個(gè)演示。
我個(gè)人不怎么喜歡通過(guò)quartz.config文件進(jìn)行配置,這樣也容易寫死,所以我還是喜歡使用最簡(jiǎn)單的NameValueCollection配置,因?yàn)樗臄?shù)據(jù)源可來(lái)源
于第三方存儲(chǔ)結(jié)構(gòu)中,配置代碼如下:
1 //1.首先創(chuàng)建一個(gè)作業(yè)調(diào)度池 2 var properties = new NameValueCollection(); 3 //存儲(chǔ)類型 4 properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz"; 5 6 //驅(qū)動(dòng)類型 7 properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz"; //數(shù)據(jù)源名稱 8 properties["quartz.jobStore.dataSource"] = "myDS"; 9 10 //連接字符
http://www.cnblogs.com/huangxincheng/p/6916246.html