4

前言:我对 Camel 还很陌生,在尽可能地消化了 Camel 的实际操作后,我正在将其调整到我正在进行的项目中。在这个项目中,我们有一些相当复杂的错误处理,我想确保我可以在我们对代码进行骆驼化时复制它。

在我们的项目中(与大多数项目一样),有一组我们想要重试的异常和一组我们不想重试的异常——但更具体地说,有一组我们想要重试的次数多于其他异常(并非所有可恢复的错误都可以处理相同)。在这种情况下,我试图定义一个onException块来更改重新投递策略。但是,似乎 Exchange 维护计数 ( Exchange.REDELIVERY_COUNTER),并且此计数不依赖于引发的异常。有没有办法让这个计数特定于给定的异常?

例如 - 我有两个例外FooExceptionBarException. 在我的路线中(或实际上在整个上下文中),我想重试 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 次尝试时,它抛出 a BarException,似乎这种工作方式是 Exchange 的 aREDELIVERY_COUNTER为 5,当我将策略重置为仅尝试两次,它(逻辑上)得出不应重试路由的结论并抛出异常。但是,在我的应用程序中BarExceptions应该重试两次,不管有多少FooExceptions被抛出。同样,如果它交替抛出 Foo 和 Bar 异常,我希望它只增加给定异常的计数器。

Camel in Action 的最后提倡使用retryWhile- 这是获取我正在寻找的那种控制的唯一方法吗?我是否需要创建一个知道每个异常计数的有状态 bean?还是我忽略了一些简单的事情?我想确保当我接近这个重构时,我不会让我们走上一条丑陋的道路。

使用骆驼 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
    {
    }
}

结果,您的同意被批准:在 BarException 之后交付尝试被用尽,即使我们只有 4 个 FooExceptions 和 1 个 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 回答