架构

路由控制器

师成师成· 更新于 2026-09-28· 阅读 16 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

路由控制器

Camel 使用 RouteController 来管理所有路由的生命周期。该控制器主要在 Camel 启动过程中启动路由时使用。

该控制器负责决定启动哪些路由,以及按什么顺序启动。

Camel 提供两种控制器:经典的默认控制器,以及可以在启动失败时尝试重新启动路由的监控控制器。

DefaultRouteController

这是 Camel 一直以来使用的默认控制器和策略。该控制器遵循快速失败原则,即如果有任何路由启动失败,它就会放弃,导致 Camel 本身启动失败。

该控制器还按顺序依次启动路由,并使用单线程。这意味着没有并发启动,路由的启动更加可靠,不会出现并发问题。

如果路由在启动时失败,通常是其 Consumer 在启动过程中触发了错误。某些组件提供了内部处理机制并尝试从中恢复。然而,大多数组件并不提供这样的功能,因此在大多数情况下,路由将无法启动,进而导致 Camel 本身也无法启动。JMS 组件就是一个能够在 Consumer 启动问题(例如无法连接到 JMS 代理)中进行恢复的组件示例。

SupervisingRouteController 能够处理这种情况,它接管启动失败的路由并尝试重新启动它们。

以下是这些路由:

  • Java
  • XML
  • YAML
from("file:foo/cake")
  .to("log:cake");

from("salesforce:cheese")
  .to("log:cheese");
<route>
    <from uri="file:foo/cake"/>
    <to uri="log:cake"/>
</route>

<route>
    <from uri="salesforce:cheese"/>
    <to uri="log:cheese"/>
</route>
- route:
    from:
      uri: file:foo/cake
      steps:
        - to:
            uri: log:cake
- route:
    from:
      uri: salesforce:cheese
      steps:
        - to:
            uri: log:cheese

那么这两条路由在启动时都可能失败。不过,使用文件组件的第一条路由很可能总是能够成功启动,因为它仅仅是使用文件系统,而文件系统是可靠的。

然而,第二条路由使用的是 Salesforce,如果没有能够连接到 Salesforce 的网络,它就可能启动失败。

SupervisingRouteController

这是一种具备监督能力的 RouteController,它会在 Camel 上下文启动之后延迟路由的启动,并以安全的方式接管路由的启动工作。该控制器能够对启动失败的路由进行重试,并提供了多种选项,用于配置路由重启之间退避(backoff)的相关设置。

我们再次使用同一个示例:

  • Java
  • XML
  • YAML
from("file:foo/cake")
  .to("log:cake");

from("salesforce:cheese")
  .to("log:cheese");
<route>
    <from uri="file:foo/cake"/>
    <to uri="log:cake"/>
</route>

<route>
    <from uri="salesforce:cheese"/>
    <to uri="log:cheese"/>
</route>
- route:
    from:
      uri: file:foo/cake
      steps:
        - to:
            uri: log:cake
- route:
    from:
      uri: salesforce:cheese
      steps:
        - to:
            uri: log:cheese

然后我们可以告诉 Camel 使用监督路由控制器,让 Camel 尝试恢复启动 Salesforce 路由。

配置监督路由控制器

通过 Java 启用并配置监督路由控制器:

  • Java
  • 应用程序属性
CamelContext camel = ...
SupervisingRouteController src = camel.getRouteController().supervise();
src.setBackOffDelay(5000);
src.setBackOffMaxAttempts(3);
src.setInitialDelay(1000);
src.setThreadPoolSize(2);

当使用 Spring Boot、Quarkus 或 Camel CLI 时

camel.routecontroller.enabled = true

# and you can configure more options
camel.routecontroller.backoffDelay = 5000
camel.routecontroller.backoffMaxAttempts = 3
camel.routecontroller.initialDelay = 1000
camel.routecontroller.threadPoolSize = 2

Spring XML

而对于使用 Spring <beans> 的用户,可以按如下方式操作:

<camelContext>
    <routeController id="myController"
                     supervising="true" initialDelay="1000" threadPoolSize="2"
                     backOffDelay="5000" backOffMaxAttempts="3"/>
    <route>
      <from uri="file:foo/cake"/>
      <to uri="log:cake"/>
    </route>
    <route>
      <from uri="salesforce:cheese"/>
      <to uri="log:cheese"/>
    </route>
</camelContext>

Supervising Route Controller 选项

你可以使用以下选项来配置 SupervisingRouteController:

选项默认值描述
Enabledfalse启用监督式路由控制器(supervising route controller)。启用后,Camel 可以先启动,随后由该控制器以安全的方式负责启动各条路由。当你希望即使某条路由在启动阶段可能快速失败并导致 Camel 启动失败,仍要让 Camel 启动起来时,可以使用此功能。通过将路由启动工作委托给监督式路由控制器,控制器会使用后台线程来管理启动过程。控制器支持多种配置设置,用于尝试重启失败的路由。
InitialDelayCamelContext 启动后,路由控制器开始工作之前的初始延迟时间,单位为毫秒。
BackOffDelay2000重启启动失败的路由时的退避延迟时间,单位为毫秒。
BackOffMaxAttempts重启启动失败的路由时的最大退避尝试次数。超过该阈值后,控制器将放弃尝试重启该路由,该路由将保持停止状态。默认情况下会无限期地持续尝试。
BackOffMaxDelay重启启动失败的路由时的最大退避延迟时间,单位为毫秒。
BackOffMaxElapsedTime最大退避总耗时时间,单位为毫秒。超过该时间后应视为退避耗尽,不再进行尝试。
BackOffMultiplier1.0用于指数退避的退避乘数,可用来延长重启尝试之间的延迟时间。
IncludeRoutes用于筛选要纳入监督范围的路由的模式。该模式会与路由 id 以及路由的端点 URI 进行匹配。多个模式之间用逗号分隔。例如,要包含所有 Kafka 路由,可以使用 kafka:;要包含具有特定路由 id 的路由,可以使用 myRoute,myOtherRoute。该模式支持通配符,使用 org.apache.camel.support.PatternHelper#matchPattern 中的匹配器。
ExcludeRoutes用于筛选要排除在监督范围之外的路由的模式。该模式会与路由 id 以及路由的端点 URI 进行匹配。多个模式之间用逗号分隔。例如,要排除所有 JMS 路由,可以使用 jms:;要排除具有特定路由 id 的路由,可以使用 mySpecialRoute,myOtherSpecialRoute。该模式支持通配符,使用 org.apache.camel.support.PatternHelper#matchPattern 中的匹配器。
ThreadPoolSize1路由控制器调度线程池用于重启路由的线程数量。线程池默认使用 1 个线程,但可以增加该值,以便在有多条路由启动出现问题时,控制器能够并发尝试重启多条路由。
UnhealthyOnExhaustedtrue当所有重启尝试(退避)均已失败、路由未能成功启动且路由管理器已放弃时,是否将该路由标记为不健康(down)。若将此项设置为 false,健康检查将忽略该问题,并允许将 Camel 应用程序报告为 UP。
UnhealthyOnRestartingtrue当路由初始启动失败、正在受控制器管理进行重启(退避)时,是否将该路由标记为不健康(down)。若将此项设置为 false,健康检查将忽略该问题,并允许将 Camel 应用程序报告为 UP。
UnhealthyOnExhausted 和 UnhealthyOnRestarting 选项在 Camel 4.6 及更早版本中默认为 false。

过滤需要快速失败的路由

使用 supervising route controller 时,默认情况下所有路由都会被监管,即使一个或多个路由启动失败,也允许 Camel 成功启动。这是因为监管器会处理这些失败的路由,并在后台尝试重启它们(带有退避策略)。

你可能有一条关键路由必须始终启动,否则就让 Camel 本身启动失败。这可以通过 include/exclude 选项将该路由从监管中过滤出来实现。

给定以下路由:

  • Java
  • XML
  • YAML
from("file:foo/cake")
  .to("log:cake");

from("salesforce:cheese")
  .to("log:cheese");

from("aws-s3:foo")
  .to("log:foo");
<route>
    <from uri="file:foo/cake"/>
    <to uri="log:cake"/>
</route>

<route>
    <from uri="salesforce:cheese"/>
    <to uri="log:cheese"/>
</route>

<route>
    <from uri="aws-s3:foo"/>
    <to uri="log:foo"/>
</route>
- route:
    from:
      uri: file:foo/cake
      steps:
        - to:
            uri: log:cake
- route:
    from:
      uri: salesforce:cheese
      steps:
        - to:
            uri: log:cheese
- route:
    from:
      uri: aws-s3:foo
      steps:
        - to:
            uri: log:foo

那么,假设只要任意一条 AWS 路由启动失败,我们就应该快速失败。这可以通过按模式 aws*(URI 或路由 ID)进行排除来实现。

  • Java
  • 应用属性
CamelContext camel = ...
SupervisingRouteController src = camel.getRouteController().supervise();
src.setBackOffDelay(5000);
src.setExcludeRoutes("aws*");

当使用 Spring Boot、Quarkus 或 Camel CLI 时

camel.routecontroller.excludeRoutes = aws*

JMX 管理

路由控制器可以通过 JMX 进行管理,你可以在 services 节点下找到它们的 MBean。

要在 Camel 中使用 JMX,classpath 中必须包含 camel-management JAR。

更多信息

当 Apache Camel 关闭时,由其优雅关机机制负责处理这一过程,以确保所有路由都能优雅、安全地关闭。

评论

登录后参与评论

正在加载评论…