交换池
Exchange 池化
路由引擎会维护每条消息的状态,跟踪消息的流转路径以及消息接下来的去向。路由引擎还负责处理错误、采集指标等复杂任务。在路由过程中的每个处理步骤,都会在堆上分配少量的 Java 对象。
正因这些路由簿记和处理工作,Apache Camel 在路由消息时需要少量的资源开销。
随着云计算的发展,工作负载被精确计量,Camel 也因此进行了一系列核心优化以降低开销。
池化对象以减少对象分配
被复用的最重要的对象是 org.apache.camel.Exchange 对象。该对象是承载消息的根对象,包含消息的载荷、标头、元数据及其他内容。
除了对 Exchange 进行池化之外,路由引擎使用的内部对象也会被池化和循环复用。这可以大幅减少 Camel 核心本身产生的对象分配。
实际的消息内容(载荷和标头)始终会产生对象分配,所使用的 Camel 组件及其第三方库也会产生对象分配。启用池化后,Camel 核心及其路由引擎的内存占用接近于零。
这一切听起来都很美好,那么有什么缺点呢?对象池化的代价在于管理池的复杂性(从池中获取对象以及将对象归还给池)。不过,这些都由 Camel 自动处理。对象池使用 JDK 的 ConcurrentMap 实例,占用的内存非常少。管理池会带来少量的 CPU 开销,包括向池中添加和移除对象,以及在复用前重置对象。
在大多数情况下,用极小的 CPU 成本换取对象分配的减少是值得的。这可以避免 JVM 垃圾回收更频繁地运行,从而提高响应速度并降低延迟(在某些情况下,垃圾回收开销会导致应用程序因“停止世界”暂停及其相关的处理开销而暂停或延迟处理消息)。
启用 Exchange 池化
对象池化目前默认是禁用的。如果你使用的是 Camel Main(来自 Camel Core)、Camel Spring Boot 或 Camel Quarkus,可以在 application.properties 中启用它:
camel.main.exchange-factory = pooled以编程方式启用 Exchange 池化
如果你使用的是其他运行时,或者希望以编程方式完成此操作,可以通过 ExtendedCamelContext 的 setExchangeFactory 方法来实现。以下是使用 Java 实现的示例:
// suppose a Camel context object declared in the scope
CamelContext context = ...
context.getCamelContextExtension().setExchangeFactory(new PooledExchangeFactory());ExtendedCamelContext 是 Camel 的内部 API,因此它可能无法提供与公共 API 相同级别的向后兼容性。请尽可能通过应用属性来配置交换池。 |
|---|
配置选项
你可以使用以下选项配置交换池:
| 选项 | 说明 | 默认值 |
|---|---|---|
| exchange-factory | 是否使用池。可选值为 prototype 或 pooled | prototype |
| exchange-factory-capacity | 池中元素的最大数量 | 100 |
| exchange-factory-statistics-enabled | 是否收集使用统计信息 | false |
管理
如果启用了对象池,Camel 会提供一个 JMX MBean,允许我们通过 JMX 检视这些池及其使用情况。这需要将 camel-management JAR 添加到类路径中。
示例
我们提供了一些用于性能剖析的示例。如果你需要一个示例,可以查看基础的 timer-log。
评论
登录后参与评论
KnowForge