当前位置: 首页 > news >正文

内容相同的 网站搜狗收录提交

内容相同的 网站,搜狗收录提交,做试用的网站,小型深圳网站页面设计集群环境可能出现的问题在上一篇博客我们介绍了如何在自己的项目中从无到有的添加了Quartz定时调度引擎,其实就是一个Quartz 和Spring的整合过程,很容易实现,但是我们现在企业中项目通常都是部署在集群环境中的,这样我们之前的定时…

集群环境可能出现的问题

在上一篇博客我们介绍了如何在自己的项目中从无到有的添加了Quartz定时调度引擎,其实就是一个Quartz 和Spring的整合过程,很容易实现,但是我们现在企业中项目通常都是部署在集群环境中的,这样我们之前的定时调度就会出现问题了,因为我们的定时任务都加载在内存中的,每个集群节点中的调度器都会去执行,这就会存在重复执行和资源竞争的问题,那么如何来解决这样的问题呢,往下面看吧...

解决方案

在一般的企业中解决类似的问题一般都是在一个note上部署Quartz其他note不部署(或者是在其他几个机器加IP地址过滤),但是这样集群对于定时任务来说就没有什么意义了,而且存在着单点故障的隐患,也就是这台部署着Quartz的机器一旦挂了,我们的定时任务就停止服务了,这绝对不是我们想要的。

Quartz本身是支持集群的,我们通过Quartz的集群方式来解决这样的问题。

Quartz集群

ae11be3e269e53d6158b3b0fd1281d36.png

虽然单个 Quartz 实例能给予你很好的 Job调度能力,但它不能令典型的企业需求,如可伸缩性、高可靠性满足。假如你需要故障转移的能力并能运行日益增多的 Job,Quartz 集群势必成为你方言的一部分了,并且即使是其中一台机器在最糟的时间崩溃了也能确保所有的 Job 得到执行。 QuartzJob Scheduling Framework

了解了Quartz集群的好处,接下来就对我们之前的工程进行改造,增加Quartz集群特性。

Quartz集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群

所以我们集群的第一步就是建立Quartz所需要的12张表:

1、建表

在quartz核心包里面通过quartz提供的建表语句建立相关表结构

f7cd132cb67c54ab22a18665c8a9d890.png

生成的表结构如下

1b36789b4cad4db8f647c4cdf63370bb.png

这几张表是用于存储任务信息,触发器,调度器,集群节点等信息

详细解释:

QRTZ_CALENDARS 以Blob 类型存储Quartz 的Calendar 信息

QRTZ_CRON_TRIGGERS 存储Cron Trigger,包括Cron 表达式和时区信息

QRTZ_FIRED_TRIGGERS 存储与已触发的Trigger 相关的状态信息,以及相联Job 的执行信息

QRTZ_PAUSED_TRIGGER_GRPS 存储已暂停的Trigger 组的信息

QRTZ_SCHEDULER_STATE 存储少量的有关Scheduler 的状态信息,和别的Scheduler 实例(假如是用于一个集群中)

QRTZ_LOCKS 存储程序的非观锁的信息(假如使用了悲观锁)

QRTZ_JOB_DETAILS 存储每一个已配置的Job 的详细信息

QRTZ_JOB_LISTENERS 存储有关已配置的JobListener 的信息

QRTZ_SIMPLE_TRIGGERS 存储简单的Trigger,包括重复次数,间隔,以及已触的次数

QRTZ_BLOG_TRIGGERS Trigger 作为Blob 类型存储(用于Quartz 用户用JDBC 创建他们自己定制的Trigger 类型,JobStore并不知道如何存储实例的时候)

QRTZ_TRIGGER_LISTENERS 存储已配置的TriggerListener 的信息

QRTZ_TRIGGERS 存储已配置的Trigger 的信息

所有的表默认以前缀QRTZ_开始。可以通过在quartz.properties配置修改(org.quartz.jobStore.tablePrefix= QRTZ_)。

2、编写quartz.properties文件

建立 quartz.properties文件把它放在工程的 src 目录下,内容如下:

1 #============================================================================

2

3 # Configure Main Scheduler Properties4

5 #============================================================================

6

7

8

9 org.quartz.scheduler.instanceName =Mscheduler10

11 org.quartz.scheduler.instanceId = AUTO

12

13 org.quartz.jobStore.clusterCheckinInterval=20000

14

15

16

17 #============================================================================

18

19 # Configure ThreadPool20

21 #============================================================================

22

23

24

25 org.quartz.threadPool.class =org.quartz.simpl.SimpleThreadPool26

27 org.quartz.threadPool.threadCount = 3

28

29 org.quartz.threadPool.threadPriority = 5

30

31

32

33 #============================================================================

34

35 # Configure JobStore36

37 #============================================================================

38

39

40

41 #org.quartz.jobStore.class =org.quartz.simpl.RAMJobStore42

43

44

45 org.quartz.jobStore.class =org.quartz.impl.jdbcjobstore.JobStoreTX46

47 #org.quartz.jobStore.driverDelegateClass =org.quartz.impl.jdbcjobstore.StdJDBCDelegate48

49 org.quartz.jobStore.useProperties = true

50

51 #org.quartz.jobStore.dataSource =myDS52

53 org.quartz.jobStore.tablePrefix =QRTZ_54

55 org.quartz.jobStore.isClustered = true

56

57 org.quartz.jobStore.maxMisfiresToHandleAtATime=1

58

59 #============================================================================

60

61 # Configure Datasources62

63 #============================================================================

64

65

66

67 #mysql68

69 #org.quartz.dataSource.myDS.driver =com.ibm.db2.jcc.DB2Driver70

71 #org.quartz.dataSource.myDS.URL = jdbc:db2://localhost:50000/db

72

73 #org.quartz.dataSource.myDS.user =db274

75 #org.quartz.dataSource.myDS.password =db276

77 #org.quartz.dataSource.myDS.maxConnections = 5

78

79

80

81 #oracle82

83 #org.quartz.dataSource.myDS.driver =oracle.jdbc.driver.OracleDriver84

85 #org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@localhost:1521:orcl86

87 #org.quartz.dataSource.myDS.user =scott88

89 #org.quartz.dataSource.myDS.password =shao90

91 #org.quartz.dataSource.myDS.maxConnections = 5

92

93

94

95 #For Tomcat96

97 org.quartz.jobStore.driverDelegateClass =org.quartz.impl.jdbcjobstore.oracle.OracleDelegate98

99 #For Weblogic &Websphere100

101 #org.quartz.jobStore.driverDelegateClass =org.quartz.impl.jdbcjobstore.WebLogicDelegate102

103 org.quartz.jobStore.useProperties = false

104

105 org.quartz.jobStore.dataSource =myDS106

107

108

109

110

111 #JNDI MODE112

113 #For Tomcat114

115 org.quartz.dataSource.myDS.jndiURL=java:comp/env/jdbc/oracle116

117 #For Weblogic &Websphere118

119 #org.quartz.dataSource.myDS.jndiURL=jdbc/oracle120

121

122

123

124

125 #============================================================================

126

127 # Configure Plugins128

129 #============================================================================

130

131

132

133 #org.quartz.plugin.triggHistory.class =org.quartz.plugins.history.LoggingJobHistoryPlugin134

135

136

137 #org.quartz.plugin.jobInitializer.class =org.quartz.plugins.xml.JobInitializationPlugin138

139 #org.quartz.plugin.jobInitializer.fileNames =jobs.xml140

141 #org.quartz.plugin.jobInitializer.overWriteExistingJobs = true

142

143 #org.quartz.plugin.jobInitializer.failOnFileNotFound = true

144

145 #org.quartz.plugin.jobInitializer.scanInterval = 10

146

147 #org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

红色加粗部分是集群需要的配置

核心配置解释如下:

org.quartz.jobStore.class 属性为JobStoreTX,

将任务持久化到数据中。因为集群中节点依赖于数据库来传播Scheduler实例的状态,你只能在使用JDBC JobStore 时应用Quartz 集群。

org.quartz.jobStore.isClustered 属性为true,通知Scheduler实例要它参与到一个集群当中。

org.quartz.jobStore.clusterCheckinInterval

属性定义了Scheduler实例检入到数据库中的频率(单位:毫秒)。

Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;

这能指出一个失败的Scheduler 实例,且当前Scheduler 会以此来接管任何执行失败并可恢复的Job。

通过检入操作,Scheduler也会更新自身的状态记录。clusterChedkinInterval越小,Scheduler节点检查失败的Scheduler 实例就越频繁。默认值是 20000 (即20 秒)

3、修改spring-time.xml文件

1 <?xmlversion ="1.0"encoding="UTF-8"?>

2 -//SPRING//DTD BEAN//EN"3 "http://www.springframework.org/dtd/spring-beans.dtd">

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

增加红色加粗部分代码,注入数据源和加载quartz.properties文件

OK Quartz集群的配置只有这几步,我们来启动项目。。。

我们启着启着….报错了!

17:00:59,718 ERROR ContextLoader:215 - Context initialization failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'startQuertz' defined in class path resource [config/spring/spring-time.xml]: Invocation of init method failed; nested exception is org.quartz.JobPersistenceException:Couldn't store job: Unable to serialize JobDataMap for insertion into database because the value of property 'methodInvoker' is not serializable: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean [See nested exception: java.io.NotSerializableException: Unable to serialize JobDataMap for insertion into database because the value of property 'methodInvoker' is not serializable: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean]

我们主要来看红色部分,主要原因就是这个MethodInvokingJobDetailFactoryBean 类中的 methodInvoking 方法,是不支持序列化的,因此在把 quartz 的 task 序列化进入数据库时就会抛这个serializable的错误

4、解决serializable错误解决方案

网上查了一下,解决这个问题,目前主要有两种方案:

4.1.修改Spring的源码

作者重写了MethodInvokingJobDetailFactoryBean

4.2.通过AOP反射对Spring源码进行切面重构

博客地址:http://blog.csdn.net/lifetragedy/article/details/6212831

根据 QuartzJobBean 来重写一个自己的类,然后使用 SPRING 把这个重写的类(我们就名命它为: MyDetailQuartzJobBean )注入 appContext 中后,再使用 AOP 技术反射出原有的 quartzJobx( 就是开发人员原来已经做好的用于执行 QUARTZ 的 JOB 的执行类 ) 。

两种方式我都进行了测试,都可以解决问题,我们这里先通过第二种方式解决这个bug,没有修改任何Spring的源码

4.2.1、增加MyDetailQuartzJobBean.Java

1 packageorg.leopard.core.quartz;2

3 importjava.lang.reflect.Method;4

5 importorg.apache.commons.logging.Log;6 importorg.apache.commons.logging.LogFactory;7 importorg.quartz.JobExecutionContext;8 importorg.quartz.JobExecutionException;9 importorg.springframework.context.ApplicationContext;10 importorg.springframework.scheduling.quartz.QuartzJobBean;11

12 /**

13 * 解决Spring和Quartz整合bug14 *15 */

16 public class MyDetailQuartzJobBean extendsQuartzJobBean {17 protected final Log logger =LogFactory.getLog(getClass());18

19 privateString targetObject;20 privateString targetMethod;21 privateApplicationContext ctx;22

23 protected void executeInternal(JobExecutionContext context) throwsJobExecutionException {24 try{25

26 logger.info("execute [" + targetObject + "] at once>>>>>>");27 Object otargetObject =ctx.getBean(targetObject);28 Method m = null;29 try{30 m = otargetObject.getClass().getMethod(targetMethod, newClass[] {});31

32 m.invoke(otargetObject, newObject[] {});33 } catch(SecurityException e) {34 logger.error(e);35 } catch(NoSuchMethodException e) {36 logger.error(e);37 }38

39 } catch(Exception e) {40 throw newJobExecutionException(e);41 }42

43 }44

45 public voidsetApplicationContext(ApplicationContext applicationContext) {46 this.ctx =applicationContext;47 }48

49 public voidsetTargetObject(String targetObject) {50 this.targetObject =targetObject;51 }52

53 public voidsetTargetMethod(String targetMethod) {54 this.targetMethod =targetMethod;55 }56

57 }

5、再次修改spring-time.xml文件解决serializable问题

修改后的spring-time.xml文件内容如下:

1 <?xmlversion ="1.0"encoding="UTF-8"?>

2 -//SPRING//DTD BEAN//EN"3 "http://www.springframework.org/dtd/spring-beans.dtd">

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33 org.leopard.core.quartz.MyDetailQuartzJobBean

34

35

36

37

38

39

40

41

42

43

44

45

46

主要看红色加粗部分...

测试

Ok  配置完成,我们把oa_ssh部署到两台tomcat上面,分别启动。

4af47b548900649bddf0c356a8649ef5.png

可以看到我们先启动的tomcat控制台打印出日志

ff03db04757f9c9f47265652b0843eb2.png

另外一台没有打印日志

094f5c06d73e437d7ae180d727a28d15.png

这时我们把执行定时任务的那台tomcat停止,可以看到等了一会之后,我们的另外一台tomcat会把之前tomcat执行的定时任务接管过来继续执行,我们的集群是成功的。

7adf780b42a1830e4807b9203912e3ee.png

http://www.lbrq.cn/news/2507977.html

相关文章:

  • wordpress做社区网站营业推广策划方案
  • 找项目网站兰州网站开发公司
  • 重庆网站推广服务seo排名工具有哪些
  • 海南建设网网站韶关seo
  • 企业品牌网站建设成都搜索优化排名公司
  • 龙岗网站建设 公司推广如何推销网站
  • 全国疫情最新消息地图seo排名优化怎样
  • 网站建设 提案 框架网络营销师报考条件
  • 专业做校园文化的网站企业推广平台有哪些
  • 新公司网站建设网站推广基本方法是
  • wordpress 企业网站 免费下载如何免费推广网站
  • 如何做英文系统下载网站郑州本地seo顾问
  • 网站建设开发报价明细整站seo排名
  • 武汉抖音seo推广网站关键词排名seo
  • 网站设置301重定向微信小程序开发公司
  • 浅析php网站建设的八大优势阿里数据
  • 关于建设政府门户网站的请示长沙seo网站优化
  • python 做企业网站优化排名 生客seo
  • 上海怎样建设网站零基础学电脑培训班
  • 上海网站建设费用多少性能优化大师
  • 要建设一个网站需要准备些什么北大青鸟软件开发培训学费多少
  • 注册公司上什么网站自动优化app
  • 阀门网站建设百度登录个人中心
  • 国外手表网站科技公司网站制作公司
  • 黑龙江省建设网站营销网络是啥意思
  • 深圳购物网站建设报价做网站哪家好
  • 怎样查看网站是用什么cms 做的今日的新闻头条10条
  • 编程自学免费网站成都网站优化公司
  • 金华市住房和城乡建设厅网站中国站长之家
  • 做幼儿园设计方案的网站免费发布广告的平台
  • 接口自动化测试pytest框架
  • Python动态规划:从基础到高阶优化的全面指南
  • Qt:盒子模型的理解
  • Java中get()与set()方法深度解析:从封装原理到实战应用
  • mac电脑安装docker图文教程
  • 实战演练1:实战演练之命名实体识别