聊聊spring cloud的consulRetryInterceptor

本文主要研究一下spring cloud的consulRetryInterceptor

consulRetryInterceptor

spring-cloud-consul-core-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/consul/ConsulAutoConfiguration.java

@Configuration
@EnableConfigurationProperties
@ConditionalOnConsulEnabled
public class ConsulAutoConfiguration {
    //......

    @ConditionalOnClass({ Retryable.class, Aspect.class, AopAutoConfiguration.class })
    @Configuration
    @EnableRetry(proxyTargetClass = true)
    @Import(AopAutoConfiguration.class)
    @EnableConfigurationProperties(RetryProperties.class)
    protected static class RetryConfiguration {

        @Bean(name = "consulRetryInterceptor")
        @ConditionalOnMissingBean(name = "consulRetryInterceptor")
        public RetryOperationsInterceptor consulRetryInterceptor(
                RetryProperties properties) {
            return RetryInterceptorBuilder.stateless()
                    .backOffOptions(properties.getInitialInterval(),
                            properties.getMultiplier(), properties.getMaxInterval())
                    .maxAttempts(properties.getMaxAttempts()).build();
        }

    }

    //......
}
  • RetryConfiguration注冊了consulRetryInterceptor伶丐,它基于RetryProperties創(chuàng)建了RetryOperationsInterceptor

RetryProperties

spring-cloud-consul-core-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/consul/RetryProperties.java

@ConfigurationProperties("spring.cloud.consul.retry")
public class RetryProperties {

    /** Initial retry interval in milliseconds. */
    private long initialInterval = 1000;

    /** Multiplier for next interval. */
    private double multiplier = 1.1;

    /** Maximum interval for backoff. */
    private long maxInterval = 2000;

    /** Maximum number of attempts. */
    private int maxAttempts = 6;

    public RetryProperties() {
    }

    public long getInitialInterval() {
        return this.initialInterval;
    }

    public void setInitialInterval(long initialInterval) {
        this.initialInterval = initialInterval;
    }

    public double getMultiplier() {
        return this.multiplier;
    }

    public void setMultiplier(double multiplier) {
        this.multiplier = multiplier;
    }

    public long getMaxInterval() {
        return this.maxInterval;
    }

    public void setMaxInterval(long maxInterval) {
        this.maxInterval = maxInterval;
    }

    public int getMaxAttempts() {
        return this.maxAttempts;
    }

    public void setMaxAttempts(int maxAttempts) {
        this.maxAttempts = maxAttempts;
    }

    @Override
    public String toString() {
        return new ToStringCreator(this).append("initialInterval", this.initialInterval)
                .append("multiplier", this.multiplier)
                .append("maxInterval", this.maxInterval)
                .append("maxAttempts", this.maxAttempts).toString();
    }

}
  • RetryProperties定義了initialInterval回懦、multiplier、maxInterval、maxAttempts屬性

AopAutoConfiguration

spring-boot-autoconfigure-2.1.6.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/aop/AopAutoConfiguration.java

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = false)
    @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
            matchIfMissing = false)
    public static class JdkDynamicAutoProxyConfiguration {

    }

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
            matchIfMissing = true)
    public static class CglibAutoProxyConfiguration {

    }

}
  • AopAutoConfiguration根據(jù)spring.aop.proxy-target-class來注入不同的代理方式穴肘,默認(rèn)是cglib代理

RetryOperationsInterceptor

spring-retry-1.2.4.RELEASE-sources.jar!/org/springframework/retry/interceptor/RetryOperationsInterceptor.java

public class RetryOperationsInterceptor implements MethodInterceptor {

    private RetryOperations retryOperations = new RetryTemplate();

    private MethodInvocationRecoverer<?> recoverer;

    private String label;

    public void setLabel(String label) {
        this.label = label;
    }

    public void setRetryOperations(RetryOperations retryTemplate) {
        Assert.notNull(retryTemplate, "'retryOperations' cannot be null.");
        this.retryOperations = retryTemplate;
    }

    public void setRecoverer(MethodInvocationRecoverer<?> recoverer) {
        this.recoverer = recoverer;
    }

    public Object invoke(final MethodInvocation invocation) throws Throwable {

        String name;
        if (StringUtils.hasText(label)) {
            name = label;
        } else {
            name = invocation.getMethod().toGenericString();
        }
        final String label = name;

        RetryCallback<Object, Throwable> retryCallback = new RetryCallback<Object, Throwable>() {

            public Object doWithRetry(RetryContext context) throws Exception {
                
                context.setAttribute(RetryContext.NAME, label);

                /*
                 * If we don't copy the invocation carefully it won't keep a reference to
                 * the other interceptors in the chain. We don't have a choice here but to
                 * specialise to ReflectiveMethodInvocation (but how often would another
                 * implementation come along?).
                 */
                if (invocation instanceof ProxyMethodInvocation) {
                    try {
                        return ((ProxyMethodInvocation) invocation).invocableClone().proceed();
                    }
                    catch (Exception e) {
                        throw e;
                    }
                    catch (Error e) {
                        throw e;
                    }
                    catch (Throwable e) {
                        throw new IllegalStateException(e);
                    }
                }
                else {
                    throw new IllegalStateException(
                            "MethodInvocation of the wrong type detected - this should not happen with Spring AOP, " +
                                    "so please raise an issue if you see this exception");
                }
            }

        };

        if (recoverer != null) {
            ItemRecovererCallback recoveryCallback = new ItemRecovererCallback(
                    invocation.getArguments(), recoverer);
            return this.retryOperations.execute(retryCallback, recoveryCallback);
        }

        return this.retryOperations.execute(retryCallback);

    }

    /**
     * @author Dave Syer
     *
     */
    private static final class ItemRecovererCallback implements RecoveryCallback<Object> {

        private final Object[] args;

        private final MethodInvocationRecoverer<?> recoverer;

        /**
         * @param args the item that failed.
         */
        private ItemRecovererCallback(Object[] args, MethodInvocationRecoverer<?> recoverer) {
            this.args = Arrays.asList(args).toArray();
            this.recoverer = recoverer;
        }

        public Object recover(RetryContext context) {
            return recoverer.recover(args, context.getLastThrowable());
        }

    }

}
  • RetryOperationsInterceptor實現(xiàn)了aopalliance的MethodInterceptor耘柱;它將invocation包裝為retryCallback腔长,然后使用RetryTemplate實現(xiàn)重試

小結(jié)

  • RetryConfiguration注冊了consulRetryInterceptor葡缰,它基于RetryProperties創(chuàng)建了RetryOperationsInterceptor
  • RetryProperties定義了initialInterval、multiplier缸榄、maxInterval渤弛、maxAttempts屬性
  • RetryOperationsInterceptor實現(xiàn)了aopalliance的MethodInterceptor;它將invocation包裝為retryCallback甚带,然后使用RetryTemplate實現(xiàn)重試

doc

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末她肯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鹰贵,更是在濱河造成了極大的恐慌晴氨,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碉输,死亡現(xiàn)場離奇詭異籽前,居然都是意外死亡,警方通過查閱死者的電腦和手機敷钾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門枝哄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阻荒,你說我怎么就攤上這事挠锥。” “怎么了侨赡?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵瘪贱,是天一觀的道長纱控。 經(jīng)常有香客問我,道長菜秦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任舶掖,我火速辦了婚禮球昨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眨攘。我一直安慰自己主慰,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布鲫售。 她就那樣靜靜地躺著共螺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪情竹。 梳的紋絲不亂的頭發(fā)上藐不,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音秦效,去河邊找鬼雏蛮。 笑死,一個胖子當(dāng)著我的面吹牛阱州,可吹牛的內(nèi)容都是我干的挑秉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼苔货,長吁一口氣:“原來是場噩夢啊……” “哼犀概!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起夜惭,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤姻灶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后滥嘴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體木蹬,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年若皱,在試婚紗的時候發(fā)現(xiàn)自己被綠了镊叁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡走触,死狀恐怖晦譬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情互广,我是刑警寧澤敛腌,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布卧土,位于F島的核電站,受9級特大地震影響像樊,放射性物質(zhì)發(fā)生泄漏尤莺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一生棍、第九天 我趴在偏房一處隱蔽的房頂上張望颤霎。 院中可真熱鬧,春花似錦涂滴、人聲如沸友酱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缔杉。三九已至,卻和暖如春搁料,著一層夾襖步出監(jiān)牢的瞬間或详,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工加缘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鸭叙,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓拣宏,卻偏偏與公主長得像沈贝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子勋乾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容