camel-quartz2:集群配置
camel-quartz2: clustering configuration
我想设置带有集群选项的 camel-quartz2 调度器。
这是我当前的coding/configuration:
package com.foo.bar.quartz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan({"com.foo.bar.quartz.camel"})
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
package com.foo.bar.quartz;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
public class ApplicationWebXml extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
application
.showBanner(false)
.sources(Application.class);
return application;
}
}
package com.foo.bar.quartz.camel;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CamelScheduler extends RouteBuilder {
@Override
public void configure() throws Exception {
from("quartz2://group1/trigger1?cron=0/2+*+*+*+*+?&stateful=true")
.routeId("quartztimer")
.setHeader("ROUTING_KEY", simple("'trigger1'"))
.log(LoggingLevel.INFO, "Yeah quartz rocks, routingKey: ${header.ROUTING_KEY}");
}
}
org.quartz.scheduler.skipUpdateCheck = true
org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.jobFactory.class = org.quartz.simpl.SimpleJobFactory
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.jobStore.clusterCheckinInterval = 20000
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/cntmx?characterEncoding=utf8
org.quartz.dataSource.myDS.user = blah
org.quartz.dataSource.myDS.password = hlab
org.quartz.dataSource.myDS.maxConnections = 12
我将此应用程序复制到 2 个单独的项目中,并将它们命名为 quartz-demo-1、quartz-demo-2。
然后我 运行 两个应用程序都在同一个 Apache 服务器上。
两个调度程序每 2 秒同时触发:
2015-09-14 14:23:28 quartz-demo-2 [MyClusteredScheduler-camel-1-1_Worker-3] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:28 quartz-demo-1 [MyClusteredScheduler-camel-1_Worker-3] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:30 quartz-demo-1 [MyClusteredScheduler-camel-1_Worker-4] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:30 quartz-demo-2 [MyClusteredScheduler-camel-1-1_Worker-4] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:32 quartz-demo-1 [MyClusteredScheduler-camel-1_Worker-5] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:32 quartz-demo-2 [MyClusteredScheduler-camel-1-1_Worker-5] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
期望的行为是每两秒应该只有一个来自任一应用程序的触发来模拟故障转移。我该如何配置这种行为?似乎两个调度程序都不知道对方,即使他们从同一个石英表中读取。
非常感谢您的帮助。
解决此问题的两种方法:
1) 在 QuartzComponent 上定义属性文件 属性。请参阅 配置 quartz.properties 文件 http://camel.apache.org/quartz2.html
--或--
2) 运行 第二个路由在不同的 JVM 上。这就是修复它的原因:
这与与 camel 上下文关联的 JMX 管理名称有关。看起来 Quartz2 组件将管理名称 (http://camel.apache.org/maven/camel-2.15.0/camel-core/apidocs/org/apache/camel/CamelContext.html#getManagementName()) 附加到 org.quartz.scheduler.instanceName 属性 中定义的名称,如果您没有像我上面描述的那样定义 propertiesFile 属性。
由于您 运行 在同一个 JVM 上,两个 camel 上下文被分配了唯一的管理名称,从而产生了唯一的调度程序名称。这将阻止集群按预期工作。
我想设置带有集群选项的 camel-quartz2 调度器。
这是我当前的coding/configuration:
package com.foo.bar.quartz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan({"com.foo.bar.quartz.camel"})
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
package com.foo.bar.quartz;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
public class ApplicationWebXml extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
application
.showBanner(false)
.sources(Application.class);
return application;
}
}
package com.foo.bar.quartz.camel;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CamelScheduler extends RouteBuilder {
@Override
public void configure() throws Exception {
from("quartz2://group1/trigger1?cron=0/2+*+*+*+*+?&stateful=true")
.routeId("quartztimer")
.setHeader("ROUTING_KEY", simple("'trigger1'"))
.log(LoggingLevel.INFO, "Yeah quartz rocks, routingKey: ${header.ROUTING_KEY}");
}
}
org.quartz.scheduler.skipUpdateCheck = true
org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.jobFactory.class = org.quartz.simpl.SimpleJobFactory
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.jobStore.clusterCheckinInterval = 20000
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/cntmx?characterEncoding=utf8
org.quartz.dataSource.myDS.user = blah
org.quartz.dataSource.myDS.password = hlab
org.quartz.dataSource.myDS.maxConnections = 12
我将此应用程序复制到 2 个单独的项目中,并将它们命名为 quartz-demo-1、quartz-demo-2。
然后我 运行 两个应用程序都在同一个 Apache 服务器上。
两个调度程序每 2 秒同时触发:
2015-09-14 14:23:28 quartz-demo-2 [MyClusteredScheduler-camel-1-1_Worker-3] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:28 quartz-demo-1 [MyClusteredScheduler-camel-1_Worker-3] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:30 quartz-demo-1 [MyClusteredScheduler-camel-1_Worker-4] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:30 quartz-demo-2 [MyClusteredScheduler-camel-1-1_Worker-4] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:32 quartz-demo-1 [MyClusteredScheduler-camel-1_Worker-5] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
2015-09-14 14:23:32 quartz-demo-2 [MyClusteredScheduler-camel-1-1_Worker-5] INFO quartztimer - Yeah quartz rocks, routingKey: 'trigger1'
期望的行为是每两秒应该只有一个来自任一应用程序的触发来模拟故障转移。我该如何配置这种行为?似乎两个调度程序都不知道对方,即使他们从同一个石英表中读取。
非常感谢您的帮助。
解决此问题的两种方法:
1) 在 QuartzComponent 上定义属性文件 属性。请参阅 配置 quartz.properties 文件 http://camel.apache.org/quartz2.html
--或--
2) 运行 第二个路由在不同的 JVM 上。这就是修复它的原因:
这与与 camel 上下文关联的 JMX 管理名称有关。看起来 Quartz2 组件将管理名称 (http://camel.apache.org/maven/camel-2.15.0/camel-core/apidocs/org/apache/camel/CamelContext.html#getManagementName()) 附加到 org.quartz.scheduler.instanceName 属性 中定义的名称,如果您没有像我上面描述的那样定义 propertiesFile 属性。
由于您 运行 在同一个 JVM 上,两个 camel 上下文被分配了唯一的管理名称,从而产生了唯一的调度程序名称。这将阻止集群按预期工作。