Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.github.timemachinelab.retry.backoff;

public interface BackoffStrategy {

long calculateDelay(int attempts);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.github.timemachinelab.retry.backoff;

public class ExponentialBackoff implements BackoffStrategy {

private final long baseDelay = 100;

private long minDelay = 100;
private long maxDelay = 5000;

@Override
public long calculateDelay(int attempts) {

long delay = (long) (baseDelay * Math.pow(2,attempts-1));
delay = Math.max(delay, baseDelay);
delay = Math.min(minDelay, delay);
return delay;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.github.timemachinelab.retry.jitter;

import java.util.concurrent.ThreadLocalRandom;

public class FullJitter implements JitterAlgorithm {

private ThreadLocalRandom random = ThreadLocalRandom.current();

@Override
public long calculateDelay(long baseDelay,long previousDelay) {
return random.nextLong(0,baseDelay+1);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.github.timemachinelab.retry.jitter;

public interface JitterAlgorithm {

long calculateDelay(long baseDelay,long previousDelay);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.github.timemachinelab.retry.retryBudget;

public interface RetryBudget {



}
33 changes: 33 additions & 0 deletions tml-sdk-spring-boot-autoconfigure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,39 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<!-- 依赖 core 模块 -->
<dependency>
<groupId>io.github.timemachinelab</groupId>
<artifactId>tml-sdk-java-core</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
</dependencies>

<scm>
<tag>master</tag>
<url>https://github.com/Time-Machine-Lab/TmlFoundation</url>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.github.timemachinelab.autoconfigure.retry;

import io.github.timemachinelab.autoconfigure.retry.aop.RetryInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
* 重试组件自动配置类
*
* @author TimeMachineLab
*/
@Configuration
@ConditionalOnClass(name = "org.aspectj.lang.annotation.Aspect")
@ConditionalOnProperty(prefix = "tml.retry", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(RetryProperties.class)
@EnableAspectJAutoProxy
public class RetryAutoConfiguration {

private static final Logger log = LoggerFactory.getLogger(RetryAutoConfiguration.class);

public RetryAutoConfiguration() {
log.info("TML Retry Component Auto Configuration initialized");
}

/**
* 注册重试拦截器
*/
@Bean
public RetryInterceptor retryInterceptor() {
log.info("Registering RetryInterceptor bean");
return new RetryInterceptor();
}

// TODO: 当你实现了 core 模块后,可以在这里注册更多 Bean
// 例如:
// @Bean
// public RetryExecutor retryExecutor(RetryProperties properties) {
// return new RetryExecutor(...);
// }
//
// @Bean
// public RetryBudget retryBudget(RetryProperties properties) {
// return new TokenBucketRetryBudget(...);
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package io.github.timemachinelab.autoconfigure.retry;

import io.github.timemachinelab.autoconfigure.retry.annotation.JitterType;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* 重试组件配置属性
*
* @author TimeMachineLab
*/
@ConfigurationProperties(prefix = "tml.retry")
public class RetryProperties {

/**
* 是否启用重试功能
*/
private boolean enabled = true;

/**
* 默认配置
*/
private DefaultConfig defaultConfig = new DefaultConfig();

/**
* 重试预算配置
*/
private BudgetConfig budget = new BudgetConfig();

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public DefaultConfig getDefaultConfig() {
return defaultConfig;
}

public void setDefaultConfig(DefaultConfig defaultConfig) {
this.defaultConfig = defaultConfig;
}

public BudgetConfig getBudget() {
return budget;
}

public void setBudget(BudgetConfig budget) {
this.budget = budget;
}

/**
* 默认重试配置
*/
public static class DefaultConfig {

/**
* 最大重试次数
*/
private int maxAttempts = 3;

/**
* 基础延迟时间(毫秒)
*/
private long baseDelay = 100;

/**
* 最大延迟时间(毫秒)
*/
private long maxDelay = 60000;

/**
* 抖动类型
*/
private JitterType jitterType = JitterType.FULL;

public int getMaxAttempts() {
return maxAttempts;
}

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

public long getBaseDelay() {
return baseDelay;
}

public void setBaseDelay(long baseDelay) {
this.baseDelay = baseDelay;
}

public long getMaxDelay() {
return maxDelay;
}

public void setMaxDelay(long maxDelay) {
this.maxDelay = maxDelay;
}

public JitterType getJitterType() {
return jitterType;
}

public void setJitterType(JitterType jitterType) {
this.jitterType = jitterType;
}
}

/**
* 重试预算配置
*/
public static class BudgetConfig {

/**
* 是否启用重试预算
*/
private boolean enabled = true;

/**
* 滑动窗口大小(秒)
*/
private int windowSize = 10;

/**
* 最大重试比例(0.0 - 1.0)
*/
private double maxRetryRatio = 0.1;

/**
* 最小请求数阈值
*/
private int minRequestsThreshold = 30;

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public int getWindowSize() {
return windowSize;
}

public void setWindowSize(int windowSize) {
this.windowSize = windowSize;
}

public double getMaxRetryRatio() {
return maxRetryRatio;
}

public void setMaxRetryRatio(double maxRetryRatio) {
this.maxRetryRatio = maxRetryRatio;
}

public int getMinRequestsThreshold() {
return minRequestsThreshold;
}

public void setMinRequestsThreshold(int minRequestsThreshold) {
this.minRequestsThreshold = minRequestsThreshold;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.github.timemachinelab.autoconfigure.retry.annotation;

/**
* 退避策略类型枚举
*
* @author TimeMachineLab
*/
public enum BackoffType {

/**
* 固定延迟
* delay = baseDelay
*/
FIXED,

/**
* 线性退避
* delay = baseDelay × attempt
*/
LINEAR,

/**
* 指数退避(推荐)
* delay = baseDelay × 2^(attempt-1)
*/
EXPONENTIAL
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.github.timemachinelab.autoconfigure.retry.annotation;

import io.github.timemachinelab.autoconfigure.retry.RetryAutoConfiguration;
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

/**
* 启用重试功能的注解
* 在 Spring Boot 配置类上使用
*
* @author TimeMachineLab
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(RetryAutoConfiguration.class)
public @interface EnableRetry {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.github.timemachinelab.autoconfigure.retry.annotation;

/**
* 抖动类型枚举
*
* @author TimeMachineLab
*/
public enum JitterType {

/**
* 全抖动:random(0, backoff)
* AWS 推荐,最大程度避免共振
*/
FULL,

/**
* 均等抖动:backoff/2 + random(0, backoff/2)
* 保证最小延迟,同时添加随机性
*/
EQUAL,

/**
* 去相关抖动:random(base, previous * 3)
* 考虑上次延迟,适合长时间重试场景
*/
DECORRELATED,

/**
* 无抖动:使用原始退避时间
*/
NONE
}
Loading