整合不同系统是一项复杂且很有挑战的工作;如果有一个像拼图一样,把已有的拼图组件拼接起来,据此来整合各个系统,这样就会很简单。系统集成框架就是做这个事情的,使用起来不用关心待集成整合的系统是如何工作的,只专注于如何从外部与它们进行交互就行,一个好的集成框架就像是把各个复杂系统通过简单的、可管理的抽象且无缝地连接在一起的“胶水”,而Apache Camel就是这样一个集成框架。

1. 什么是Camel

1.1 来源

Camel项目开始于2007年初,虽然年轻,但它已经是一个成熟的开源项目,基于自由的Apache 2许可,已拥有一个强大的社区。

Apache Camel项目之所以被命名为Camel,只因为简单好记而已,不过也有传言说这个名字的灵感来自于其中一个创始人,让曾抽过骆驼牌香烟。在骆驼的网站上有一个FAQ条目(http://camel.apache.org/why-the-name-camel.html)列出了其他理由,有兴趣可以去看下。

1.2 特点

  1. 路由引擎:Camel的核心是一个路由引擎,更准确地说是一个路由引擎构建器。它允许使用者定义自己的路由规则,根据路由规则决定从接收哪个源头的消息,然后经过自定义的处理,将消息发送到指定的目的地。Camel使用一种集成语言来定义相对复杂的路由规则,就像定义业务流程一样。

  2. 不关心数据类型:Camel的一个基本原则是它不规范数据类型,这样开发人员可以据此集成任何类型的系统,而不需关心这些系统处理的数据类型是怎样的。

  3. 不关心交互协议:Camel提供了更高级的抽象,允许您使用相同的API与各种系统进行交互,而不必关心这些系统使用的协议或数据类型是什么。而这些都是因为Camel本身已经提供了针对不同的协议和数据类型的API的特定实现; 目前Camel支持超过80个协议和数据类型,并且基于其可扩展和模块化架构,允许开发人员自定义实现逻辑并可无缝地插入到集成系统处理逻辑中。

基于上面的这些特点和其本身的体系结构,使得Camel不仅跑得快,而且很轻量。

另外,这里也要特别说明下,Camel不是企业服务总线,尽管有些人因为Camel支持路由、转换、监视、编排等这些功能而将其称为轻量级的ESB。但是Camel并没有引入具有容量或可靠的消息总线,不过Camel确实可以实现对消息总线的兼容,如Open-ESB、ServiceMix。所以Camel是集成框架,而不是ESB。

1.3 核心能力

1.3.1 路由引擎

上面已经提到过,Camel的核心是一个路由引擎,更准确地说是一个路由引擎构建器。

1.3.2 企业集成模式

在Gregor Hohpe和Bobby Woolf的《企业集成模式》一书中,其提到虽然企业系统集成有很多问题,但是很多问题和解决方法都很相似。这个就很像JAVA开发中共你的设计模式一样,企业系统集成也有一定的模式,或者说方法论可寻,这就是企业集成模式EIPs。Camel很大程度上是基于EIPs来实现的,虽然EIPs描述了很多集成问题和解决思路,但它只是解决思路,而Camel是用一种语言来具体实现了这些思路。

1.3.3 领域特定语言(DSL)

Camel的领域特定语言(DSL)是对系统集成的一个主要贡献。目前也有一起支持DSL的集成框架,但都是基于通用语言,而Camel与的不同之处在于,Camel提供了多语言的DSL,如常规编程语言Java、Scala、Groovy,并且Camel还支持通过XML定义路由规则。

DSL的目的是让开发人员专注于集成问题而不是集成工具(编程语言)。虽然Camle是Java开发的,但Camel支持多种语言混合编程。每种语言都有自己的特点和优势,我们可以使用不同的语言来完成不同的任务,然后使用Camel来进行自由的改造和整合。这里有一个例子:

  • Java DSL
from("file:data/inbox").to("jms:queue:order");
  • Spring DSL
<route>
 <from uri="file:data/inbox"/>
 <to uri="jms:queue:order"/> 
</route>
  • **Scala DSL **
from "file:data/inbox" -> "jms:queue:order"

1.3.4 丰富且可扩展的组件包库

Camel提供了可扩展的80多种组件(Component)包库,通过这些组件Component可以让Camel连上不同的通道,使用不同的API、识别不同的数据类型。

1.3.5 支持各种格式的消息内容

Camel可以路由各种形式的消息,绝不仅仅是只有XML格式,这也就意味着在路由的过程中不用把我们的消息内容转换成某一指定的规范格式。

1.3.6 模块化和可插拔的架构设计

Camel是模块化架构,允许将任何组件加载到其中,且无论组件是来自于Camel系统,还是任何其他第三方系统,亦或是我们自己构建的其他系统。

1.3.7 POJO模型

基于面向对象思想,在Camel中,bean(或pojo)被认为是一流的公民,并且Camel允许我们随时随地在集成项目中使用这些bean。据此,我们可以在很多地方把自己的自定义代码扩展到Camel的内置功能中。

1.3.8 易于配置

Camel基于"约定大于配置"(Convention Over Configuration)的原则,尽量减少配置任务;Camel提供了简便且人性化的URL配置方式,直接把端点(Endpoints)配在路由(Rourte)。

例如,配置一个文件消费者,目的是递归扫描子文件夹查找其中只包括.txt文件的文件夹,如下:

from("file:data/inbox?recursive=true&include=*.txt")...

1.3.9 类型自由转换

Camel内置了类型转换器,提供了150多种转换,比如字节数组转换为字符串,如果Camel现有不支持,那么我们可以自定义自己的类型转换器;不过目前常用的大多数类型的数据转换,Camel都已经做好了

1.3.10 轻量的核心

Camel的核心库只有大约1.6 MB,只依赖Apache Commons Logging和FuseSource Commons Management,是相当的轻量,所以我们可以把Camel很轻松的嵌入到到任何地方,如独立应用程序、web应用程序、Spring应用程序、JavaEE应用程序,JBI容器,OSGi bundle, Java Web Start或谷歌应用程序引擎。

这也是Camel的设计初衷,其不是作为服务器或ESB,而是嵌入到任何你需要的平台中。

1.3.11 提供测试组件

Camel提供了一个Test Kit,方便我们更容易地测试自己的Camel程序;这个测试套件包含了超过6000个单元测试。

1.3.12 活跃的社区

Camel有一个活跃的社区:https://camel.apache.org/community/

2. Camel的消息模型

2.1 消息模型分类

在Camel中,有两种用于消息模型:

1、org.apache.camel.message:实体消息,包含具体业务数据的消息,需要在Camel中路由的数据

2、org.apache.camel.Exchange:交换消息,是Camel的一个抽象概念,有"in"消息(入),"out"消息(出)

2.2 消息

消息是系统在使用时用来相互通信的实体消息通道。消息向着一个方向从发送者流到接收者,如图下图所示:

image-20211012161016088

消息有body(主体)、headers(头信息)、attachments(属性),如下图:

image-20211012161153156

消息使用字符类型的标识符进行唯一标识,标识符的惟一性是强制的;该标识符由消息创建者保证,没有固定格式,但并依赖不同的协议;若协议没有定义唯一性的消息标识,则Camel将会使用自己的UID生成器生成唯一标识。

2.2.1 消息头信息和属性(headers 和 attachments)

headers头信息是与消息相关的一些信息,如例如发送者UID、内容编码、认证等等;以k-v键值对形式存在,key需唯一且是不区分大小写的字符串,value为java对象。这意味着Camel没有施加任何类型约束。

attachments属性是消息的可选信息,通常用于web服务和电子邮件服务。

2.2.2 消息主体(body)

消息主体类型是java.lang.Object,所以消息主体可以存储任何类型的内容。

同时,这也意味着应用程序设计人员要确保接收者要能够理解待接收的消息内容。

当发送者和接收者使用不同的主体格式时,我们可以使用Camel提供的很多转换器来将消息主体转换为可接受的格式。

2.2.3 失败标志 (FAULT FLAG)

消息也有一个错误标志。一些协议和规范,如WSDL和JBI,是区分输出消息和错误消息的。它们都是对响应的校验操作,但后者错误消息明确指示一个不成功的结果。

一般来说,集成基础设施不处理错误,这应该是客户端和服务端协议的一部分;错误应该是在应用程序级别进行处理。

在Camel中,消息的路由是通过包含在Exchange中完成的。

2.3 Exchange

Camel中的一个exchange就是消息路由流转过程中的一个消息容器。

通过Exchange可以实现系统之间不同类型的集成,例如众所周知的MEPs(Message exchange patterns)。MEPs 被用来区分单向消息(one-way)和双向消息(request-response)。

在Camel中的Exchange可选择如下消息模式:

  1. InOnly:单向消息 (事件),例如JMS 消息
  2. InOut:双向消息(request-response),例如HTTP消息。

Exchange的包含的内容如下图:

image-20211012164511469

  1. Exchange ID:Exchange的唯一标识,若没有设置,则Camel将会自动生成一个默认的唯一标识;
  2. MEP:消息模式(Inonly或InOut),当InOnly模式时,Exchange只包含一种in消息。若是InOut模式,Exchange将会包含请求和响应;
  3. Exception:当消息路由流转过程中发生错误,那么将会有一个Exception设置到Exchange的这个属性中;
  4. Properties:相似消息头信息,但他们会持续贯穿某个消息的整个路由流转的全过程。这里面一般存放某个消息内容的全局性(global-leve)的属性信息,而消息头信息是用来标记消息本身的。在路由期间Camel框架将会添加自己的各种属性到Properties;同样作为开发者,我们通过Properties可以在消息路由流转交换的全生命周期内的任何地方保存或获取恢复全局性的某些属性;
  5. In message:输入消息,这是必需的,包含请求数据信息;
  6. Out message:输出消息,可选的,仅仅是Exchange的消息模式是InOut模式时才会有,包含响应数据信息。

3. Camel架构

3.1 Camel整体架构

Camel由processors处理器、components组件和routes路由组成,所有这些都是包含在CamelContext中的。
image-20211012170637947

  1. Routing engine:路由引擎,消息路由的详细说明;router路由是使用Camel的一种领域特定语言(DSL)定义的;
  2. Processors:消息处理器,消息路由流转期间的各种转换和操作,以实现各种EIP(企业集成模式);
  3. Components:组件,是Camel中连接其他系统的扩展点。

3.2 CamelContext(Camel运行时上下文)

CamelContext是一个容器,其保存了Camel运行时的所有系统碎片信息,下图展示了CamelContext中保留的值得注意的部分内容:

image-20211012172051626

service描述
Components包含所有运行时使用的组件,Camel能够在运行时动态加载组件(不管是通过类路径下的自动发现还是OSGI容器中的自动激活包)
Endpoints包含已创建的endpoints
Routes包含被添加的所有路由
Type converters包含已载入的所有类转换,Camel拥有手动或自动转换类型的机制
Registry包含可以查阅beans的注册表,默认情况下,它是JNDI registry;若基于Spring,则将是Spring ApplicationContext ;若使用OSGI容器,则将是OSGI registry
Languages包含载入的语言,Camel允许使用不同的语言创建表达式

文献:《Camel In Action》 Meeting Camel

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐