4

序文: 私は Camel にかなり慣れていないので、Camel の動作を可能な限り消化した後、自分が取り組んでいるプロジェクトに適応させています。このプロジェクトでは、かなり複雑なエラー処理がいくつかあります。コードを Camel 化する際に、これを確実に複製できるようにしたいと考えています。

私たちのプロジェクトには(ほとんどの場合)、再試行したい例外のセットとそうでないセットがありますが、より具体的には、他のものよりも再試行したいセットがあります(すべての回復可能なエラーを処理できるわけではありません同じ)。この場合、onExceptionブロックを定義して再配信ポリシーを変更しようとしました。ただし、Exchange はカウント ( Exchange.REDELIVERY_COUNTER) を保持しており、このカウントはスローされた例外に依存していないようです。このカウントを特定の例外に固有にする方法はありますか?

たとえば、私には 2 つの例外がFooExceptionありBarExceptionます。私のルート (または実際にはコンテキスト全体) では、FooExceptions を 10 回再試行したいのですが、BarExceptions は 2 回だけ再試行する必要があります。したがって、コンテキストには次が含まれます。

<onException>
     <exception>my.exception.FooException</exception>
     <redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000"
</onException>

<onException>
      <exception>my.exception.BarException</exception>
      <redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000"
</onException>

さて、懸念事項 - アプリケーションが aFooExceptionをスローして 4 回再試行し (毎回 a をスローするFooException)、5 回目の試行で をスローするBarExceptionと、Exchange の aREDELIVERY_COUNTERは 5 になるようです。ポリシーを 2 回だけ試行するようにリセットすると、(論理的に) ルートを再試行すべきではないと判断され、例外がスローされます。ただし、私のアプリケーションでは、スローされたBarExceptions回数に関係なく、2 回再試行する必要があります。FooExceptions同様に、Foo 例外と Bar 例外を交互にスローする場合は、特定の例外のカウンターのみをインクリメントしたいと思います。

Camel in Action の最後で、retryWhile私が探している種類のコントロールを取得するには、これが唯一の方法ですか? 例外ごとのカウントを認識するステートフル Bean を作成する必要がありますか? それとも単純なものを見落としていますか?このリファクタリングに取り組む際に、醜い道を歩み始めないようにしたいと思います。

Camel 2.10.1 の使用

4

2 に答える 2

1

次のテストであなたのケースをチェックしました:

import org.apache.camel.EndpointInject;
import org.apache.camel.Exchange;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicLong;

/**
 * @author Illarion Kovalchuk
 *         Date: 12/7/12
 *         Time: 2:58 PM
 */
public class Test extends CamelTestSupport
{

    private static final String MIDDLE_QUEUE = "seda:middle";

    @EndpointInject(uri = "mock:result")
    protected MockEndpoint resultEndpoint;

    @Produce(uri = "direct:start")
    protected ProducerTemplate template;

    private Processor processor = new Processor();

    @Test
    public void shouldRedeliverOnErrors() throws Exception
    {
        resultEndpoint.expectedBodiesReceived("Body");
        template.sendBodyAndHeader(MIDDLE_QUEUE, "Body", "Header", "HV");
        resultEndpoint.assertIsNotSatisfied();
    }

    @Override
    protected RouteBuilder createRouteBuilder()
    {
        return new RouteBuilder()
        {
            @Override
            public void configure() throws Exception
            {

                onException(FooException.class)
                        .redeliveryDelay(2000)
                        .maximumRedeliveries(10);

                onException(BarException.class)
                        .redeliveryDelay(5000)
                        .maximumRedeliveries(2);

                from(MIDDLE_QUEUE)
                        .bean(Processor.class, "process")
                        .to(resultEndpoint)
                        .end();
            }
        };
    }

    public static class Processor
    {
        private static AtomicLong retryState = new AtomicLong(0L);

        public static void process(Exchange e) throws FooException, BarException
        {
            long rs = retryState.getAndAdd(1L);
            if (rs < 4)
            {
                System.err.println("Foo Attempt "+ rs);
                throw new FooException();
            }
            if (rs == 4)
            {
                System.err.println("Bar Attempt "+ rs);
                throw new BarException();
            }
            System.err.println("Normal Attempt "+ rs);
        }
    }

    public static class FooException extends Throwable
    {
    }

    private static class BarException extends Throwable
    {
    }
}

その結果、あなたの懸念は承認されました。4 つの FooException と 1 つの BarException しかない場合でも、BarException の後に配信の試行が使い果たされます。

残念ながら、今はあなたの質問に完全に答えることはできません。

于 2012-12-07T15:49:10.037 に答える
0

例外を定義する順序を置き換えてみてください。たとえば、次のようになります。

<onException>
      <exception>my.exception.BarException</exception>
      <redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000"
</onException>

<onException>
     <exception>my.exception.FooException</exception>
     <redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000"
</onException>
于 2013-01-05T15:36:05.250 に答える