Apache Camel SEDA implements the Staged Event-Driven Architecture pattern, enabling in-VM asynchronous messaging that decouples producers from consumers via BlockingQueue. This excels in high-load scenarios where synchronous endpoints like Direct would block threads—SEDA queues messages instead, boosting scalability with configurable concurrent consumers.
Core Advantages
- Non-blocking Producers: Senders complete instantly while slow consumers process from the queue, preventing cascade failures.
- Thread Pool Efficiency: Multiple consumers (
concurrentConsumers=3) parallelize work without manual thread management. - Configurable Resilience: Options like
queueSize,discardWhenFull, andofferTimeouthandle overload gracefully.
Example
This standalone app uses Camel Main (Camel 4.x) with a custom ExchangeFormatter to visualize thread names, exchange IDs, and route context—clearly demonstrating SEDA's parallel consumer threads. Producers fire 5 messages rapidly (100ms intervals) into SEDA, while consumers lag with 1s delays; logs reveal immediate sends followed by staggered, multi-threaded processing.
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spi.ExchangeFormatter;
/**
* Apache Camel example demonstrating SEDA (Staged Event-Driven Architecture) pattern.
* Shows asynchronous message processing with concurrent consumers and queuing.
*/
public class SedaExample {
static void main(String[] args) throws Exception {
// Create a new Camel Main instance (using fully qualified name to avoid conflict)
org.apache.camel.main.Main main = new org.apache.camel.main.Main();
// Add routes with SEDA processing
main.configure().addRoutesBuilder(new RouteBuilder() {
@Override
public void configure() {
// Create a custom ExchangeFormatter for detailed log output
ExchangeFormatter customFormatter = exchange ->
String.format("[Thread: %s] Body: %s | ExchangeId: %s | RouteId: %s",
Thread.currentThread().getName(),
exchange.getIn().getBody(String.class),
exchange.getExchangeId(),
exchange.getFromRouteId());
// Register the custom formatter in the Camel registry
getContext().getRegistry().bind("customFormatter", customFormatter);
// SEDA endpoint: queueId=myQueue, concurrent consumers for parallelism
from("seda:myQueue?concurrentConsumers=3")
.log("Processing: ${body}")
.delay(1000) // Simulate slow consumer (1s delay)
.to("log:output?showAll=true&exchangeFormatter=#customFormatter");
// Producer route for demo
from("timer:tick?repeatCount=5&delay=100") // Fire 5 msgs quickly
.setBody().simple("Msg ${exchangeId}")
.log("Sending: ${body}")
.to("seda:myQueue");
}
});
// Run Camel (will run until Ctrl+C is pressed)
main.run(args);
}
}
Running and Verification
Compile and run the Java class directly (requires Camel 4.14.0 on classpath). Sample output shows the advantage:
Sending: Msg 1CB44DE50955685-0000000000000000 // Producer thread - instant
Sending: Msg 1CB44DE50955685-0000000000000001 // Producer continues rapidly
output - [Thread: Camel (camel-1) thread #6 - Delay] Body: Msg 1CB44DE50955685-0000000000000000 | ExchangeId: 1CB44DE50955685-0000000000000002 | RouteId: route1
output - [Thread: Camel (camel-1) thread #7 - Delay] Body: Msg 1CB44DE50955685-0000000000000001 | ExchangeId: 1CB44DE50955685-0000000000000004 | RouteId: route1 // Parallel consumers
Contrast with direct:myQueue: sends block behind delays on single thread. SEDA's queue absorbs bursts across threads, perfect for enterprise workloads like order processing.
Recent Comments