Camel 的 SEDA、Direct 和 VM 组件指南

Camel 的 SEDA、Direct 和 VM 组件指南

Apache Camel 中的 SEDA、Direct、Direct-VM 和 VM 组件、它们的作用以及何时可以使用它们。带有代码示例。

Camel 的 SEDA、Direct 和 VM 组件指南

在设计 Camel 路线时,您有时可能希望路线具有多个输入。也许你想从Web服务接收消息JMS队列

不能在同一个路由中有多个from()方法,那么你怎么能在同一个路由中有多个入口点呢?

同样,您可能希望在多个地方重用相同的 Camel 消息处理逻辑,那么如何避免重复代码呢?

这两个问题的答案是使用 Camel 的内存中消息传递组件将您的路由连接在一起:Direct、Direct-VM、VM 和 SEDA。

在本文中,我将解释这些组件中的每一个,它们有何不同,以及如何使用它们使您的路由更加模块化和更棒。

首先……一个示例场景

首先,我将从一个例子开始。

我定义了一个路由,通过将消息传递给某个底层系统来验证传入的订单。我的订单最初是通过 JMS 消息到达的。

Camel 的 SEDA、Direct 和 VM 组件指南

但是,当订单开始来自新来源(例如文件上传或 Web 服务调用)时会发生什么?

为了避免重复相同的路由代码,Camel 具有内置功能,允许路由具有多个输入,通过使用一系列连接组件将这些路由粘合在一起。

那么它是怎样工作的?Camel 使用组件 Direct、VM 和 SEDA 将端点粘合在一起。

这些组件以不同的方式将您的 Camel 路线连接在一起。它们统称为 Camel 的内存中消息组件,因为它们允许消息在路由之间传递,而消息始终保留在内存中。这是一个非常重要的细节,我稍后会再次提及。

但是现在,让我们看看这些组件中的每一个,看看它们有什么不同,以及您可以在哪里使用它们。

Direct component

这一定是 Camel 初学者最常问到的问题之一:

路径中的“direct”是什么意思?

Camel 的 SEDA、Direct 和 VM 组件指南

您可能已经在网络上的许多 Camel 教程中看到过这些代码direct:...。但direct实际上有什么作用呢?

Apache Camel 的Direct 组件是一种将路由连接在一起的方式。当它作为路由中的启动组件使用时,可以从其他路由中调用,作为触发路由的一种方式。由于 Direct 是一个同步组件,因此在同一线程中继续执行。

direct是将您的路线链接在一起的最简单的方法之一。当它在from()定义中使用时,它会创建一个可以被其他 Camel 路由调用的同步端点。例如,这段以from(direct)开头的代码:

from("direct:yourname")...

...将创建一个名为yourname. 这同一个端点然后可以在另一个被调用to()语句别的地方,就像这样:

.to("direct:yourname");  // sends the message to the direct:yourname endpoint

在示例中,它经常被使用,因为它提供了一个简单的路由入口点,而不必公开 Web 服务,或以其他方式依赖外部接口。

示例:使用 Direct 组件
让我们用一个例子来说明 Direct 组件:
from("file:/home/files/in")       // receive a file
  .to("direct:processTheFile"); // send to direct endpoint
  .to("Body is now ${body}");   // will print 'Eggs!'

// meanwhile...    
from("direct:processTheFile")     // receive from direct endpoint
  .setBody("Eggs!");            // modify the message body</code>

但是,Direct 的简单性也有一些缺点。

直接端点只能被在同一个 CamelContext和同一个 JVM中运行的其他路由访问。这意味着您不能从另一个 CamelContext 访问 Direct 端点。请记住,CamelContext 是创建和启动 Camel 路由的容器。

那么如果你想访问另一个 CamelContext 中的路由会发生什么?您使用下一个组件 Direct-VM。

这个非常简单的示例使用 Camel 的 File 组件接收文件。处理的每个文件都作为 Exchange 传递到直接端点processTheFile

另外,我们已将processTheFile端点定义为修改消息正文的路由的起始组件。完成此操作后,新消息将返回到调用路由。所有这些都是在同一个线程中同步发生的。

Direct-VM component

Direct-VM 是一个组件,它允许您同步调用同一 JVM 中的另一个端点,即使它位于不同的CamelContext 中

当用作启动组件时,Direct-VM 将该路由公开为可以从另一个路由同步调用的端点。

Direct-VM 组件的不同之处在于,direct-vm 端点可以从其他 Camel Contexts 中看到,只要它们共享相同的 Java 虚拟机 (JVM)。

示例:使用 Direct-VM 组件
如果我们想炫耀 Direct-VM 组件,我们可以在应用程序 A 中定义一个路由:

java from("file:src/files/input") .to("direct-vm:process-file") // invoke the direct-vm endpoint

这将调用此 Direct 端点,位于应用程序 B 中...:

java from("direct-vm:process-file") // receive from direct-vm endpoint .to("log:samplelog"); // log the message

只要这两个应用程序都在同一个 JVM 中运行——例如,在同一个 Spring Boot 应用程序中使用一个应用程序容器,如 Apache Karaf、Wildfly 甚至不同的 CamelContexts——那么应用程序 A 将能够调用direct-vm应用程序中的端点B.

这开辟了将不在同一 CamelContext 中开发的路由链接在一起的可能性。例如,如果您在一个容器中部署了不同的 CamelContexts,您可能会使用此组件 - 例如当您部署到 JBoss FuseTalend ESB 时

SEDA组件

Camel 的 SEDA 组件允许您使用简单的queue将路由连接在一起。

在 Camel 路由中,当消息被发送到 SEDA 端点时,它被存储在一个基本的内存队列中,并且控制立即返回到调用路由。

然后,SEDA 使用者独立地从队列中提取消息,并开始处理它。

示例:使用 SEDA 组件
下面是一个 SEDA 队列的例子:

java rest("/orders").post() // receive an order via REST .to("seda:processOrder"); // send to the seda queue .setBody("Thanks for ordering!"); // create a REST response

from(“seda:processOrder”) // 从 seda 队列接收 .log(“Processing an order…”) .to(“file:orders/out”);</code>

在上面的示例中,消息将通过 REST 服务接收并发布到 SEDA 端点。消息到达processOrderSEDA 端点并进行处理,然后使用该file:组件将它们写入磁盘上的某个位置。

SEDA 通过创建自己的缓冲区来实现这一点,该缓冲区用于存储传入的消息。SEDA 开箱即用地创建了一个线程池来处理传入的消息,这意味着可以一次处理多条消息,从而使其可能具有更高的性能。

通过这种方式,可以将 SEDA 视为 JMS 队列的简单替代品。它提供了类似队列的功能,但没有运行像 ActiveMQ 这样的外部消息代理的开销。

请记住,Camel 将消息异步发布到 SEDA 端点。

您只能访问位于同一 CamelContext 中的SEDA 端点。那么如果你想向另一个 CamelContext 中的 SEDA 队列发送消息会发生什么您使用下一个组件 VM。

VM component

与 Direct 和 Direct-VM 的关联方式类似,VM 是与 SEDA 类似的组件。

当用作启动组件时,SEDA 允许从另一个路由异步调用一个路由。

然而,SEDA 和 VM 之间的区别在于VM 组件允许从不同的 Camel 上下文访问端点,只要它们运行在同一个 JVM 中即可。

同样,VM 组件开启了以异步方式将不在同一 Camel 上下文中开发的路由链接在一起的可能性。

SEDA 和 VM 的缺点

使用像 SEDA 和 VM 这样的内存消息传递的最大缺点是,如果应用程序崩溃,很有可能会丢失所有消息

如果您设计的集成类型与消息丢失无关紧要,那么这不是主要考虑因素。

但是回想一下本文顶部的订单处理示例。如果订单在服务器中断期间丢失,这可能意味着失去业务。(呃哦。)

考虑一下何时适合使用这些内存中的消息传递组件,以及何时将消息移交给外部消息代理(例如ActiveMQ )更合适,以确保可靠性。

没有硬性规定。正确的解决方案始终取决于您的用例。因此,在使用 Camel 设计集成时,请考虑丢失消息时该怎么办。会有关系吗?如果是这样,请考虑使用事务和持久消息传递来最大程度地减少任何消息丢失。

总结和最佳实践

所以现在您已经了解了每个组件,您应该使用哪个,以及何时使用?

SEDA 与 Direct

  • 对于同一 CamelContext 中的同步(请求/响应)交互,请使用Direct

  • 对于同一 CamelContext 中的异步(即发即忘)处理(以类似队列的方式处理消息),请使用SEDA

VM 与 Direct-VM:

  • 对于不同 CamelContext在同一个 JVM 中的**同步(请求/响应)交互,使用Direct-VM**

  • 对于不同 CamelContext在同一 JVM 中的**异步(即发即忘)交互,请使用VM**

Direct、SEDA、VM 和 Direct-VM 的比较

此表比较了每个组件,并显示它们是否可以从另一个 CamelContext(在同一 JVM 中)访问

Component 类型 来自同一个 CamelContext 来自另一个 CamelContext
Direct 同步 是的
Direct-VM 同步 是的 是的
SEDA 异步 是的
VM 异步 是的 是的
上一篇:[AGC012E] Camel and Oases


下一篇:Apache Camel源码研究之CamelInternalProcessor