2.9. 控制路由启动和关闭
概述
默认情况下,当 Apache Camel 应用程序(由 CamelContext
实例表示)启动时自动启动路由,并在您的 Apache Camel 应用程序关闭时自动关闭路由。对于非关键部署,关闭序列的详情通常并不重要。但在生产环境中,现有任务在关闭期间应该运行非常关键,以避免数据丢失。您通常还希望控制路由关闭的顺序,这样依赖项就不会被违反(这样会导致现有任务无法运行完成)。
因此,Apache Camel 提供了一组功能来支持 安全关闭 应用程序。安全关闭可让您完全控制停止和启动路由,允许您控制路由的关闭顺序,并使当前任务能够运行完成。
设置路由 ID
最好为每个路由分配一个路由 ID。除了提高日志记录消息和管理功能外,使用路由 ID 可让您对停止和启动路由应用更多的控制。
例如,在 Java DSL 中,您可以通过调用 routeId()
命令来将路由 ID myCustomerRouteId
分配到路由,如下所示:
from("SourceURI").routeId("myCustomRouteId").process(...).to(TargetURI);
在 XML DSL 中,设置 route
元素的 id
属性,如下所示:
<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring"> <route id="myCustomRouteId" > <from uri="SourceURI"/> <process ref="someProcessorId"/> <to uri="TargetURI"/> </route> </camelContext>
禁用自动启动路由
默认情况下,CamelContext 知道在启动时的所有路由都将自动启动。如果您想手动控制特定路由的启动启动,您可能需要为该路由禁用自动启动。
要控制 Java DSL 路由是否自动启动,可调用 autoStartup
命令,使用 布尔值
参数(true
或 false
)或 String
参数(true
或 false
)。例如,您可以在 Java DSL 中禁用路由的自动启动,如下所示:
from("SourceURI") .routeId("nonAuto") .autoStartup(false) .to(TargetURI);
您可以通过在路由元素上将 autoStartup
属性设置为 false
来禁用在 XML DSL 中自动启动 路由的
自动启动,如下所示:
<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring"> <route id="nonAuto" autoStartup="false"> <from uri="SourceURI"/> <to uri="TargetURI"/> </route> </camelContext>
手动启动和停止路由
您可以通过调用 CamelContext
实例的 startRoute()
和 stopRoute()
方法,随时在 Java 中手动启动或停止路由。例如,要启动具有路由 ID nonAuto
的路由,在 CamelContext
实例( 上下文
)上调用 startRoute()
方法,如下所示:
// Java context.startRoute("nonAuto");
要停止具有路由 ID nonAuto
的路由,调用 CamelContext
实例上的 stopRoute()
方法,上下文
,如下所示:
// Java context.stopRoute("nonAuto");
路由启动顺序
默认情况下,Apache Camel 以非确定的顺序启动路由。但是,在某些应用程序中,控制启动顺序非常重要。要在 Java DSL 中控制启动顺序,请使用 startupOrder()
命令,该命令使用正整数值作为其参数。具有最低整数值的路由首先启动,后接具有后续启动顺序值的路由。
例如,以下示例中的前两个路由通过 seda:buffer
端点链接在一起。您可以通过分配启动顺序(2 和 1)来保证在第二个路由片段 后 启动第一个路由片段,如下所示:
例 2.5. Java DSL 中的启动顺序
from("jetty:http://fooserver:8080") .routeId("first") .startupOrder(2) .to("seda:buffer"); from("seda:buffer") .routeId("second") .startupOrder(1) .to("mock:result"); // This route's startup order is unspecified from("jms:queue:foo").to("jms:queue:bar");
在 Spring XML 中,您可以通过设置 route
元素的 startupOrder
属性来实现相同的效果,如下所示:
例 2.6. XML DSL 中的启动顺序
<route id="first" startupOrder="2"> <from uri="jetty:http://fooserver:8080"/> <to uri="seda:buffer"/> </route> <route id="second" startupOrder="1"> <from uri="seda:buffer"/> <to uri="mock:result"/> </route> <!-- This route's startup order is unspecified --> <route> <from uri="jms:queue:foo"/> <to uri="jms:queue:bar"/> </route>
必须为每个路由 分配一个唯一的 启动顺序值。您可以选择小于 1000 的正整数值。为 Apache Camel 保留 1000 和 over 的值,这会自动将这些值分配给路由,而不显示显式启动值。例如,上例中最后一个路由会自动分配启动值 1000(因此在前两个路由后启动)。
关闭序列
当 CamelContext
实例时,Apache Camel 使用可插入关闭 策略控制关闭 序列。默认关闭策略实施以下关闭序列:
- 路由以 相反的 启动顺序关闭。
- 通常,关闭策略会等待当前活动的交换发生。但是,运行任务的处理是可配置的。
- 总体而言,关闭序列由超时(默认为 300 秒)绑定。如果关闭序列超过此超时,则关闭策略将强制关闭,即使有些任务仍在运行。
路由关闭顺序
路由以相反的启动顺序关闭。也就是说,当使用 boot-rder ()
命令(在 Java DSL 中)或 startupOrder
属性(在 XML DSL 中)定义启动顺序时,第一个关闭路由是第一个关闭的路由,由启动顺序分配 最高 的整数值。最后一个要关闭的路由是按照启动顺序分配 的最低 整数值的路由。
例如,在 例 2.5 “Java DSL 中的启动顺序” 中,需要关闭的第一个路由段是 ID、第一个
的路由,而要关闭的第二个路由段则是 ID 为 second
的路由。本例演示了一个常规规则,您应该在关闭路由时观察这些规则: 公开外部可访问消费者端点的路由应首先关闭,因为这有助于通过路由图的剩余部分来节流消息流。
Apache Camel 还提供选项 shutdownRoute(Defer)
,它可让您指定路由必须位于关闭的最后一个路由中(覆盖了启动顺序值)。但是您很少需要此选项。这个选项主要是作为早期版本的 Apache Camel(prior 到 2.3)的一个临时解决方案,哪个路由会按照 与启动顺序相同的 顺序关闭。
关闭路由中正在运行的任务
如果关闭启动时路由仍在处理消息,关闭策略通常会等待当前活跃交换完成处理后再关闭路由。可以使用 shutdownRunningTask
选项在每个路由上配置此行为,该选项可采用以下值之一:
ShutdownRunningTask.CompleteCurrentTaskOnly
- (默认) 通常,路由一次只在一条信息上运行,因此您可以在当前任务完成后安全地关闭路由。
ShutdownRunningTask.CompleteAllTasks
- 指定这个选项,以安全地关闭 批处理消费者。有些消费者端点(如 File、FTP、邮件、iBATIS 和 JPA)一次在批量消息上运行。对于这些端点,更适合等待当前批处理中的所有消息都已完成。
例如,要正常关闭文件消费者端点,您应该指定 CompleteAllTasks
选项,如以下 Java DSL 片段所示:
// Java
public void configure() throws Exception {
from("file:target/pending")
.routeId("first").startupOrder(2)
.shutdownRunningTask(ShutdownRunningTask.CompleteAllTasks)
.delay(1000).to("seda:foo");
from("seda:foo")
.routeId("second").startupOrder(1)
.to("mock:bar");
}
同一路由可以在 XML DSL 中定义,如下所示:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<!-- let this route complete all its pending messages when asked to shut down -->
<route id="first"
startupOrder="2"
shutdownRunningTask="CompleteAllTasks">
<from uri="file:target/pending"/>
<delay><constant>1000</constant></delay>
<to uri="seda:foo"/>
</route>
<route id="second" startupOrder="1">
<from uri="seda:foo"/>
<to uri="mock:bar"/>
</route>
</camelContext>
关闭超时
关闭超时的默认值为 300 秒。您可以通过在 shutdown 策略上调用 setTimeout()
方法来更改超时值。例如,您可以将超时值更改为 600 秒,如下所示:
// Java // context = CamelContext instance context.getShutdownStrategy().setTimeout(600);
与自定义组件集成
如果您正在实施自定义 Apache Camel 组件(也会从 org.apache.camel.Service
接口继承),您可以确保自定义代码通过实施 org.apache.camel.spi.ShutdownPre
ed 接口来接收关闭通知。这为组件提供了在准备关闭过程中执行自定义代码的机会。
2.9.1. RouteIdFactory
根据消费者端点,您可以添加 RouteIdFactory
,以使用逻辑名称分配路由 ID。
例如,当将路由用于 seda 或 direct 组件作为路由输入时,您可能希望使用其名称作为路由 id,如:
- direct:foo- foo
- seda:bar- bar
- JMS:orders- order
您可以使用 NodeIdFactory
为路由分配逻辑名称,而不是使用自动分配的名称。另外,您可以将上下文路由 URL 用作名称。例如,执行以下命令以使用 RouteIDFactory
:
context.setNodeIdFactory(new RouteIdFactory());
可以从其他端点获取自定义路由 id。