| = Exchange Pooling |
| |
| The routing engine keeps the state of each message, tracking the message flow, and where the messages are going next. The routing engine also handles complex tasks such as error handling, capturing metrics, and many other things. A small number of Java objects are allocated on the heap for each processing step during routing. |
| |
| Because of this routing bookkeeping and processing, Apache Camel requires a tiny resource overhead when routing messages. |
| |
| With the advance of cloud computing, where workloads are precisely measured, then Camel has undergone a series of core optimizations to reduce its overhead. |
| |
| == Pooling objects to reduce object allocations |
| |
| The most significant object being reused is the `org.apache.camel.Exchange` object. This object is the root object |
| that holds the message with its payload, headers, metadata, and other content. |
| |
| Besides pooling exchanges, the internal objects used by the routing engine are also pooled and recycled. This can dramatically reduce the object allocations from Camel core itself. |
| |
| There will always be object allocations from the actual message content (payload and headers), and also from the Camel components in use and its 3rd party libraries. The footprint of Camel core and its routing engine is close to zero when pooling is enabled. |
| |
| This all sounds marvelous so what are the negative aspects? The price to pay for object pooling is the complexity of managing the pool (acquiring and returning objects to the pool). However, all of this is taken care of by Camel itself. The object pools are using JDK `ConcurrentMap` instances and take up very little memory. Managing the pool causes a small CPU overhead associated with adding and removing objects from the pools, and resetting the objects before reuse. |
| |
| In most cases, it may be possible to sacrifice the very tiny CPU cost in exchange for reduced object allocations. This can improve responsiveness and reduce latency by preventing the JVM garbage collection from running more frequently (under some circumstances, the garbage collection overhead can cause your application to halt or delay processing messages due to stop-the-world pauses and other processing overhead associated with it). |
| |
| == Enabling Exchange Pooling |
| |
| The _object pooling_ is currently disabled by default. If you are using Camel Main (from Camel Core), Camel Spring Boot, or Camel Quarkus, then you can enable this in the `application.properties`: |
| |
| [source,properties] |
| ---- |
| camel.main.exchange-factory = pooled |
| ---- |
| |
| === Enabling Exchange Pooling on Camel 3.x |
| |
| If you are using a different runtime or want to do that programmatically, you can do so in Camel version 3 (Camel 3.x) using the `setExchangeFactory` method from the `ExtendedCamelContext`. Here's an example of how to do that using Java: |
| |
| [source,java] |
| ---- |
| // suppose a Camel context object declared in the scope |
| CamelContext context = ... |
| |
| context.adapt(ExtendedCamelContext.class).setExchangeFactory(new PooledExchangeFactory()); |
| ---- |
| |
| [NOTE] |
| ==== |
| The `ExtendedCamelContext` is an internal API of Camel and, as such, may not offer the same level of backward compatibility as the public APIs. Whenever possible, configure the exchange pooling via application properties. |
| ==== |
| |
| === Enabling Exchange Pooling on Camel 4.x |
| |
| If you are using a different runtime or if you want to do that programmatically, you can do so in Camel 4 and newer versions using the `setExchangeFactory` method from the `ExtendedCamelContext`. Here's an example of how to do that using Java: |
| |
| [source,java] |
| ---- |
| CamelContext context = ... |
| context.getExchangeExtension().setExchangeFactory(new PooledExchangeFactory()); |
| ---- |
| |
| [NOTE] |
| ==== |
| The `ExtendedCamelContext` is an internal API of Camel and, as such, may not offer the same level of backward compatibility as the public APIs. Whenever possible, configure the exchange pooling via application properties. |
| ==== |
| |
| == Configuration Options |
| |
| You can configure exchange pooling with the following options: |
| |
| [width="100%",cols="25%,50%,25%",options="header"] |
| |=== |
| |Option |Description | Default |
| | exchange-factory | Whether to use pooling or not. Possible values are prototype or pooled | prototype |
| | exchange-factory-capacity | Maximum number of elements in the pool | 100 |
| | exchange-factory-statistics-enabled | Whether to capture usage statistics | false |
| |=== |
| |
| == Management |
| |
| If object pooling is enabled, then Camel provides a JMX MBean which allows us to introspect the pools and their usage via JMX. This requires adding `camel-management` JAR to the classpath. |
| |
| == Examples |
| |
| We have provided a few examples which we are using for performance profiling. |
| You can check the basic https://github.com/apache/camel-performance-tests/tree/main/profiling/timer-log[timer-log] if you need an example. |
| |
| |