Camel SEDA エンドポイント

Apache Camel Advent Calendar 11日目の記事は、サポート担当古市が担当します。 テーマは、「Camel SEDA エンドポイント」

Camel 3.x から、従来のルーティングエンジンに加え、リアクティブエンジンが追加されました。 リアクティブに処理をするのであれば、敢えて asynchronous な処理を提供する sedaエンドポイントを使用するメリットがあるのか、改めて振り返ってみましょう。 camel.apache.org

まずは、direct エンドポイントを使ったこちらのルート。

    @Override
    public void configure() throws Exception {
        from("timer:java?repeatCount=1")
            .routeId("timer")
            .setBody()
                .simple("Hello Camel from ${routeId}")
            .to("direct:input")
            .log("${body}");

        from("direct:input")
                    .routeId("input")
                    .log("Sleep for 3sec")
                    .process(e -> {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException ex) {
                            throw new IOException(ex);
                        }
                    })
                    .log("Woke up")
                    .setBody()
                        .simple("Bye Camel from ${routeId}");
    }

実行結果はこのようになります。

2025-09-11 08:59:52.158  INFO 8365 --- [ - timer://java] ObserveThreading.java:18                 : Sleep for 3sec
2025-09-11 08:59:55.159  INFO 8365 --- [ - timer://java] ObserveThreading.java:26                 : Woke up
2025-09-11 08:59:55.162  INFO 8365 --- [ - timer://java] ObserveThreading.java:14                 : Bye Camel from input

ポイントは、Camel ルーティングエンジンによる個々のコンポーネント実行がリアクティブであっても、実行順序はリニアです。(request/reply)

次に directエンドポイントを sedaエンドポイントに置き換えて実行します。

    @Override
    public void configure() throws Exception {
        from("timer:java?repeatCount=1")
            .routeId("timer")
            .setBody()
                .simple("Hello Camel from ${routeId}")
            .to("seda:input")
            .log("${body}");

        from("seda:input")
                    .routeId("input")
                    .log("Sleep for 3sec")
                    .process(e -> {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException ex) {
                            throw new IOException(ex);
                        }
                    })
                    .log("Woke up")
                    .setBody()
                        .simple("Bye Camel from ${routeId}");
    }
}

実行結果はこちら。

2025-09-11 08:57:23.490  INFO 7972 --- [ - timer://java] ObserveThreading.java:14                 : Hello Camel from timer
2025-09-11 08:57:23.490  INFO 7972 --- [ - seda://input] ObserveThreading.java:18                 : Sleep for 3sec
2025-09-11 08:57:26.493  INFO 7972 --- [ - seda://input] ObserveThreading.java:26                 : Woke up

sedaエンドポイントから始まる "input"ルートの実行結果を待たずに、"timer"ルートの処理が終了しています。(fire/forget)

つまり、"fire/forget"パターンのデザインを使うべきか、"request/reply"パターンのデザインを使うべきかを踏まえて、directエンドポイントもしくは sedaエンドポイントの使い分けをするのが良いでしょう。 sedaエンドポイント自体もオプションが豊富です。独自にスレッドプールを使いリクエストを処理していますので、キューサイズや同時処理数など、ご利用される際はスレッドプールのチューニングもお忘れなく。

camel.apache.org

スレッド調整に興味を持たれた方は、こちらの記事もご確認ください。

camel.apache.org

明日の advent calendar 12日目では、「Camel Split/Aggrergate」 についてご紹介します。 アドベントカレンダーの一覧はこちらです。 qiita.com

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。