sequence

This article consulRetryInterceptor of Spring Cloud

consulRetryInterceptor

Spring – the cloud – consul – core – 2.1.2. RELEASE – sources. The 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) {
			returnRetryInterceptorBuilder.stateless() .backOffOptions(properties.getInitialInterval(), properties.getMultiplier(), properties.getMaxInterval()) .maxAttempts(properties.getMaxAttempts()).build(); }} / /... }Copy the code
  • RetryConfiguration registered consulRetryInterceptor, it is based on founded RetryOperationsInterceptor RetryProperties

RetryProperties

Spring – the cloud – consul – core – 2.1.2. RELEASE – sources. The 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*/ private double multiplier = 1.5; /** Maximum intervalfor 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(); }}Copy the code
  • RetryProperties defines the initialInterval, Multiplier, maxInterval, and maxAttempts attributes

AopAutoConfiguration

Spring – the boot – autoconfigure – 2.1.6. RELEASE – sources. The 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 {

	}

}
Copy the code
  • AopAutoConfiguration according tospring.aop.proxy-target-classTo inject different proxy methods, the default is cglib proxy

RetryOperationsInterceptor

Spring – retry – 1. RELEASE – sources. The jar! /org/springframework/retry/interceptor/RetryOperationsInterceptor.java

public class RetryOperationsInterceptor implements MethodInterceptor { private RetryOperations retryOperations = new RetryTemplate(); private MethodInvocationRecoverer<? > recoverer; private String label; public voidsetLabel(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());
		}

	}

}
Copy the code
  • RetryOperationsInterceptor realized aopalliance MethodInterceptor; It wraps the Invocation as retryCallback and then uses RetryTemplate for the retry

summary

  • RetryConfiguration registered consulRetryInterceptor, it is based on founded RetryOperationsInterceptor RetryProperties
  • RetryProperties defines the initialInterval, Multiplier, maxInterval, and maxAttempts attributes
  • RetryOperationsInterceptor realized aopalliance MethodInterceptor; It wraps the Invocation as retryCallback and then uses RetryTemplate for the retry

doc

  • RetryProperties