- 介绍功能和需求背景
- 介绍代码上下文,思路,方案。
- 讲解代码,评委穿插提问。参会的其他同学有问题也可以提。
- 评委对代码给建议和反馈
你有一个苹果,我有一个苹果,交换一下我们还是只有一个苹果;你有一本书,我有一本书,交换一下我们就有两本书了。每个程序员都有自己的工具集和代码私库,如果大家一起贡献出来,我们就会有一套较完整的工具集,相信可以解决大部分问题。
作为一个程序员,一个工科生,现实中的理想就是有一套趁手的完整的工具套件,家里有点什么事情,只要拿出我的工具套件就能自己轻松搞定。跟现实中一样,我们中间件团队也在默默的打造自己的软件工具套件,也希望更多的同学一起来打造这一套称心的软件工具套件。
- 流程执行完后会将流程实例调用http接口上报到星云服务端,若星云服务端不可用,不会发起重试,导致流程虽然执行完成,但是在控制台查看不到对应流程实例信息。
-
- - 改造成上报失败按(指数退避算法)策略,在一段时间后重试,确保流程实例能够上传到服务端
- - 若上传失败,在尝试若干次后记录日志并发送告警给对应业务负责人
网关应用原先依赖MetaQ,改造升级后内部的重试策略也是继承一致的重试策略,按固定级别(1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h)退避。
发送消息时设置重试策略,目前支持两种重试策略
1、【普通模式】:默认模式,强烈建议用该模式,该模式间隔会逐步递增(5s,10s,30s,60s... 逐渐递增,总周期为7天,总共20次)。
2、【表达式模式】:
距离上次重试的时间间隔 = 首次重试间隔 + 已重试次数 * 重试时间间隔步长 * 首次重试间隔(秒)
在表达式模式的策略下,最大重试、首次重试间隔和步长才会生效。注意普通模式下,以下参数不生效。
调度限流重试策略
主动限流使用随机数,5~15分钟
- jobDetail.setRedoIntervalMode(RedoIntervalModeConstant.EXPRESSION);
- // 最大重试次数,默认99次
- jobDetail.setFailRedoCountMax(10);
- // 首次重试间隔(秒)
- jobDetail.setFailFirstRedoInterval(5);
- // 重试时间间隔步长,如设置成0,则每次重试间隔相同,如设置成1,则间隔是5、10、15...
- jobDetail.setFailRedoIntervalStep(0);
根据策略获取下一次重试间隔
根据策略获取指定次数的重试间隔
多种退避算法,如指数退避、固定步长、等差数列、自定义固定级别退避,以及不退避。
可以设置最大重试间隔,如最大重试间隔不能超过1小时
可以设置最大重试次数,如最大重试20次
可以获取当前重试次数,即已经执行了几次
可以获取从开始到当前流逝的全部时间
可以获取从开始到指定次数流逝的全部时间
标准化重试策略和接口,方便延迟调度平台使用
- <dependency>
- <groupId>com.github.rholder</groupId>
- <artifactId>guava-retrying</artifactId>
- <version>1.0.6</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>4.3.17.RELEASE<version>
- </dependency>
- public interface BackOff {
-
- /**
- * Start a new back off execution.
- * @return a fresh {@link BackOffExecution} ready to be used
- */
- BackOffExecution start();
-
- }
- package org.springframework.util.backoff;
-
- /**
- * Represent a particular back-off execution.
- *
- *
Implementations do not need to be thread safe.
- *
- * @author Stephane Nicoll
- * @since 4.1
- * @see BackOff
- */
- public interface BackOffExecution {
-
- /**
- * Return value of {@link #nextBackOff()} that indicates that the operation
- * should not be retried.
- */
- long STOP = -1;
-
- /**
- * Return the number of milliseconds to wait before retrying the operation
- * or {@link #STOP} ({@value #STOP}) to indicate that no further attempt
- * should be made for the operation.
- */
- long nextBackOff();
-
- }
- package com.xxx.commons.retry.backoff;
-
- /**
- * @created 2021-12-20 4:26 PM
- * @description:
- */
- public interface Backoff {
-
- /**
- * 开始
- *
- * @return
- */
- BackoffExecution start();
-
- }
- package com.xxx.commons.retry.backoff;
-
- import java.util.concurrent.TimeUnit;
-
- /**
- * @created 2021-12-20 4:26 PM
- * @description:
- */
- public interface BackoffExecution {
- /**
- * 不再重试时返回的值
- */
- long STOP = -1;
-
- /**
- * The default time unit
- */
- TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
-
- /**
- * 下一次退避时间
- *
- * @return nextBackoff 下一次重试延迟时间(毫秒),不再重试时返回{@link #STOP} ({@value #STOP})
- */
- long nextBackoff();
-
- /**
- * 根据重试次数获取指定次数的退避时间
- *
- * @param attempt
- * @return
- */
- long getBackoff(int attempt);
-
- /**
- * 从开始到现在一共经过的时间
- *
- * @return
- */
- long getElapsedTime();
-
- /**
- * 从开始到指定次数一共经过的时间
- *
- * @param attempt
- * @return
- */
- long getElapsedTime(int attempt);
-
- /**
- * 当前尝试次数
- *
- * @return currentAttempt
- */
- int currentAttempt();
-
- }
| 接口与类 | 功能说明 | 备注说明 |
| com.xxx.commons.retry.RetryService | 重试服务工具类 | |
| com.xxx.commons.retry.backoff.Backoff | 退避算法定义接口 | |
| com.xxx.commons.retry.backoff.BackoffExecution | 退避算法执行接口 | |
| com.xxx.commons.retry.backoff.BackoffType | 退避算法类型接口 | |
| com.xxx.commons.retry.backoff.BackoffTypeEnum | 退避算法类型枚举类 | |
| com.xxx.commons.retry.backoff.CustomBackoff | 自定义序列退避算法实现 | |
| com.xxx.commons.retry.backoff.ExponentialBackoff | 指数退避算法实现 | |
| com.xxx.commons.retry.backoff.FixedBackoff | 固定步长退避算法实现 | |
| com.xxx.commons.retry.backoff.GradualBackoff | 等差数列退避算法实现 | |
| com.xxx.commons.retry.backoff.NoneBackoff | 不退避算法实现 | |
| com.xxx.commons.retry.backoff.FibonacciBackoff | 裴波那契退避算法实现 | 暂未实现 |
- package com.xxx.commons.retry.backoff;
-
- /**
- * @created 2021-12-31 3:24 PM
- * @description:
- */
- public interface BackoffType {
-
- /**
- * 类型编码
- *
- * @return
- */
- int getCode();
-
- /**
- * 类型名字
- *
- * @return
- */
- String getName();
-
- /**
- * 类型说明
- *
- * @return
- */
- String getDesc();
- }
- package com.xxx.commons.retry.backoff;
-
- /**
- * 重试补偿步长类型
- *
- * @created 2021-12-20 4:29 PM
- * @description:
- */
- public enum BackoffTypeEnum implements BackoffType {
- /**
- * 无补偿
- **/
- NONE(0, "none", "无补偿"),
-
- /**
- * 固定步长
- **/
- FIXED(1, "fixed", "固定步长"),
-
- /**
- * 等差步长
- */
- GRADUAL(2, "gradual", "等差步长"),
-
- /**
- * 指数退避
- **/
- EXPONENTIAL(3, "exponential", "指数退避"),
-
- /**
- * 自定义步长
- */
- CUSTOM(4, "custom", "自定义步长"),
-
- ;
-
- private int code;
- private String name;
- private String desc;
-
- BackoffTypeEnum(int code, String name, String desc) {
- this.code = code;
- this.name = name;
- this.desc = desc;
- }
-
- public static BackoffTypeEnum typeOf(int code) {
- for (BackoffTypeEnum type : BackoffTypeEnum.values()) {
- if (type.code == code) {
- return type;
- }
- }
- return null;
- }
-
- @Override
- public int getCode() {
- return code;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public String getDesc() {
- return desc;
- }
- }
- package com.xxx.commons.retry;
-
- /**
- * @created 2021-12-31 3:21 PM
- * @description:
- */
-
- import com.xxx.commons.retry.backoff.*;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.concurrent.*;
-
- public class RetryService {
-
- static {
- Runtime.getRuntime().addShutdownHook(RetryServiceShutdownHook.instance());
- }
-
- /**
- * 重试线程池大小
- */
- public static final int RETRY_CORE_POOL_SIZE = Integer.getInteger(
- RetryConstants.DEFAULT_RETRY_SERVICE_SCHEDULED_THREAD_POOL_SIZE_KEY,
- RetryConstants.DEFAULT_RETRY_SERVICE_SCHEDULED_THREAD_POOL_DEFAULT_SIZE);
-
- /**
- * 重试服务线程池
- */
- final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(RETRY_CORE_POOL_SIZE);
-
- private static final RetryService instance = new RetryService();
-
- public static RetryService getInstance() {
- return instance;
- }
-
- private RetryService() {
- RetryServiceShutdownHook.instance().addExecutor(executor);
- }
-
- public ScheduledFuture> retry(Callable callable, long delay) {
- return executor.schedule(callable, delay, BackoffExecution.DEFAULT_TIME_UNIT);
- }
-
- public ScheduledFuture> retry(Runnable runnable, long delay) {
- return executor.schedule(runnable, delay, BackoffExecution.DEFAULT_TIME_UNIT);
- }
-
- public ScheduledFuture> retry(Callable callable, long delay, TimeUnit unit) {
- return executor.schedule(callable, delay, unit);
- }
-
- public ScheduledFuture> retry(Runnable runnable, long delay, TimeUnit unit) {
- return executor.schedule(runnable, delay, unit);
- }
-
- public interface RetryConstants {
- String DEFAULT_RETRY_SERVICE_SCHEDULED_THREAD_POOL_SIZE_KEY = "default.retry.service.scheduled.thread.pool.size";
- int DEFAULT_RETRY_SERVICE_SCHEDULED_THREAD_POOL_DEFAULT_SIZE = 8;
- }
-
- static class RetryServiceShutdownHook extends Thread {
-
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- private List
executors = Collections.synchronizedList(new ArrayList()); - private final static RetryServiceShutdownHook instance = new RetryServiceShutdownHook();
-
- public static RetryServiceShutdownHook instance() {
- return instance;
- }
-
- private RetryServiceShutdownHook() {
- }
-
- public RetryServiceShutdownHook addExecutor(ExecutorService executor) {
- executors.add(executor);
- return this;
- }
-
- @Override
- public void run() {
- logger.info("retry service shutdown");
-
- for (int i = 0; i < executors.size(); i++) {
- ExecutorService executorService = executors.get(i);
- try {
- if (!executorService.isShutdown()) {
- executorService.shutdown();
- }
- } catch (Exception e) {
- logger.error("retry service shutdown executor service error", e.getMessage());
- }
- }
- }
- }
-
-
- }
- package com.xxx.commons.retry.backoff;
-
-
- import com.xxx.commons.data.constant.CommonConstants;
-
- import java.io.Serializable;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
-
- /**
- * @created 2021-12-27 9:47 AM
- * @description: 自定义序列退避算法实现
- */
- public class CustomBackoff implements Backoff, Serializable {
-
- private static final long serialVersionUID = 5677908306014056187L;
-
- public static final String DEFAULT_SEPARATOR = CommonConstants.SPACE_SEPARATOR;
- public static final String LEFT_BRACKET = "{";
- public static final String RIGHT_BRACKET = "}";
-
- /**
- * Constant value indicating an unlimited number of attempt.
- */
- public static final int UNLIMITED_ATTEMPTS = Integer.MAX_VALUE;
-
- /**
- * 默认退避时间序列
- * 示例1:1 2 3 10 10 10 30 60 120 180 600 1800 3600 3600 3600 3600 3600 3600
- * 示例2:1s 2s 3s 10s 10s 10s 30s 1m 2m 3m 10m 30m 1h 1h 1h 1h 1h 1h
- * 示例3:1 2 3 10{3} 30 60 120 180 600 1800 3600{6}
- * 示例4:1s 2s 3s 10s{3} 30s 1m 2m 3m 10m 30m 1h{6}
- */
- public static final String DEFAULT_SEQUENCE = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h{64}";
-
-
- /**
- * 自定义退避序列
- */
- private String sequence = DEFAULT_SEQUENCE;
-
- /**
- * 最大尝试次数
- */
- private int maxAttempt = UNLIMITED_ATTEMPTS;
-
- /**
- * 自定义序列分隔符
- */
- private String separator = DEFAULT_SEPARATOR;
-
-
- /**
- * Create an instance with an sequence with DEFAULT.
- */
- public CustomBackoff() {
- }
-
- /**
- * Create an instance.
- *
- * @param sequence the origin sequence
- */
- public CustomBackoff(String sequence) {
- this.sequence = sequence;
- }
-
- public CustomBackoff(String sequence, String separator) {
- this.sequence = sequence;
- this.separator = separator;
- }
-
- public CustomBackoff(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- public CustomBackoff(String sequence, int maxAttempt) {
- this.sequence = sequence;
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * @param sequence the origin sequence
- * @param maxAttempt the maximum number of attempt
- * @param separator the sequence's separator
- */
- public CustomBackoff(String sequence, int maxAttempt, String separator) {
- this.sequence = sequence;
- this.maxAttempt = maxAttempt;
- this.separator = separator;
- }
-
- /**
- * Set the maximum number of attempt in milliseconds.
- */
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Return the maximum number of attempt in milliseconds.
- */
- public int getMaxAttempt() {
- return maxAttempt;
- }
-
- public String getSeparator() {
- return separator;
- }
-
- public void setSeparator(String separator) {
- this.separator = separator;
- }
-
- @Override
- public BackoffExecution start() {
- return new CustomBackoffExecution(this.sequence, this.maxAttempt, this.separator);
- }
-
- public static class CustomBackoffExecution implements BackoffExecution, Serializable {
-
- private static final long serialVersionUID = 2991013977130023823L;
-
- /**
- * 自定义退避序列
- */
- private String sequence;
-
- /**
- * 最大尝试次数
- */
- private int maxAttempt;
-
- /**
- * 自定义序列分隔符
- */
- private String separator;
-
- /**
- * 解析后的退避时间间隔列表
- */
- private List
intervals; -
- private long currentElapsedTime = 0;
-
- private int currentAttempt = 0;
-
- public CustomBackoffExecution() {
- this(DEFAULT_SEQUENCE, UNLIMITED_ATTEMPTS, DEFAULT_SEPARATOR);
- }
-
- public CustomBackoffExecution(String sequence, int maxAttempt, String separator) {
- this.sequence = sequence;
- this.maxAttempt = maxAttempt;
- this.separator = separator;
- this.parse();
- }
-
- private void parse() {
- intervals = new ArrayList<>();
-
- HashMap
timeUnitTable = new HashMap(); - timeUnitTable.put("s", 1000L);
- timeUnitTable.put("m", 1000L * 60);
- timeUnitTable.put("h", 1000L * 60 * 60);
- timeUnitTable.put("d", 1000L * 60 * 60 * 24);
-
- String[] fields = sequence.split(separator);
- boolean completed = false;
- for (String field : fields) {
- field = field.trim();
- int count = 1;
- long multiple = 1;
- int leftBracket = field.indexOf(CustomBackoff.LEFT_BRACKET);
- int rightBracket = field.indexOf(CustomBackoff.RIGHT_BRACKET);
- if (leftBracket > 0 && rightBracket > 0) {
- count = Integer.parseInt(field.substring(leftBracket + 1, rightBracket));
- field = field.substring(0, leftBracket);
- }
- Long unit = timeUnitTable.get(String.valueOf(field.charAt(field.length() - 1)));
- if (unit != null) {
- multiple = unit.longValue();
- field = field.substring(0, field.length() - 1);
- }
- long timeInMills = Long.parseLong(field) * multiple;
- for (int i = 0; i < count; i++) {
- if (this.intervals.size() < this.maxAttempt) {
- this.intervals.add(timeInMills);
- } else {
- completed = true;
- }
- }
- if (completed) {
- break;
- }
- }
- // if maxAttempt greater than intervals's size, then set intervals's size as maxAttempt
- if (this.intervals.size() < this.maxAttempt) {
- this.maxAttempt = this.intervals.size();
- }
- }
-
- @Override
- public int currentAttempt() {
- return currentAttempt;
- }
-
- @Override
- public long getElapsedTime() {
- return this.currentElapsedTime;
- }
-
- @Override
- public long nextBackoff() {
-
- if (currentAttempt >= maxAttempt) {
- return STOP;
- }
-
- if (currentAttempt >= this.intervals.size()) {
- return STOP;
- }
-
- long nextInterval = this.intervals.get(this.currentAttempt);
- this.currentElapsedTime += nextInterval;
- this.currentAttempt += 1;
- return nextInterval;
- }
-
- @Override
- public void updateCurrentAttempt(int attempt) {
- if (attempt < 0) {
- this.currentAttempt = 0;
- } else if (attempt >= maxAttempt) {
- this.currentAttempt = maxAttempt;
- } else {
- this.currentAttempt = attempt;
- }
- this.currentElapsedTime = this.getElapsedTime(this.currentAttempt);
- }
-
- @Override
- public long getBackoff(int attempt) {
-
- if (attempt <= 0) {
- return 0L;
- }
-
- if (attempt - 1 >= maxAttempt) {
- return STOP;
- }
-
- if (attempt > this.intervals.size()) {
- return STOP;
- }
-
- return this.intervals.get(attempt - 1);
- }
-
- @Override
- public long getElapsedTime(int attempt) {
- if (attempt >= maxAttempt) {
- attempt = maxAttempt;
- }
-
- if (attempt >= this.intervals.size()) {
- attempt = this.intervals.size();
- }
- long elapsedTime = 0;
- for (int i = 0; i < attempt; i++) {
- elapsedTime += this.intervals.get(i);
- }
-
- return elapsedTime;
- }
-
- public String getSequence() {
- return sequence;
- }
-
- public void setSequence(String sequence) {
- this.sequence = sequence;
- }
-
- @Override
- public int getMaxAttempt() {
- return maxAttempt;
- }
-
- @Override
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- public String getSeparator() {
- return separator;
- }
-
- public void setSeparator(String separator) {
- this.separator = separator;
- }
-
- public List
getIntervals() { - return intervals;
- }
-
- public void setIntervals(List
intervals) { - this.intervals = intervals;
- }
-
- public long getCurrentElapsedTime() {
- return currentElapsedTime;
- }
-
- public void setCurrentElapsedTime(long currentElapsedTime) {
- this.currentElapsedTime = currentElapsedTime;
- }
-
- public int getCurrentAttempt() {
- return currentAttempt;
- }
-
- public void setCurrentAttempt(int currentAttempt) {
- this.currentAttempt = currentAttempt;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("CustomBackoff{");
- sb.append("intervals=").append(intervals);
- String attemptValue = (maxAttempt == Integer.MAX_VALUE ?
- "unlimited" : String.valueOf(maxAttempt));
- sb.append(", maxAttempt=").append(attemptValue);
- sb.append(", currentElapsedTime=").append(currentElapsedTime);
- sb.append(", currentAttempt=").append(this.currentAttempt);
- sb.append('}');
- return sb.toString();
- }
- }
-
- public static void main(String[] args) {
- BackoffExecution backoffExecution = new CustomBackoff().start();
- System.out.println(backoffExecution.getBackoff(1));
- System.out.println(backoffExecution.getBackoff(2));
- System.out.println(backoffExecution.getBackoff(3));
- System.out.println(backoffExecution.getElapsedTime(1));
- System.out.println(backoffExecution.getElapsedTime(2));
- System.out.println(backoffExecution.getElapsedTime(3));
- }
-
- }
- package com.xxx.commons.retry.backoff;
-
- import java.io.Serializable;
- import java.util.concurrent.TimeUnit;
-
- /**
- * @created 2021-12-20 4:31 PM
- * @description:
- */
- public class ExponentialBackoff implements Backoff, Serializable {
-
- private static final long serialVersionUID = -3955367506662250971L;
-
- /**
- * The default initial interval.
- */
- public static final long DEFAULT_INITIAL_INTERVAL = 2000L;
-
- /**
- * The default multiplier (increases the interval by 50%).
- */
- public static final double DEFAULT_MULTIPLIER = 2;
-
- /**
- * The default maximum back off time.
- */
- public static final long DEFAULT_MAX_INTERVAL = 10 * 60 * 1000L;
-
- /**
- * Constant value indicating an unlimited number of attempt.
- */
- public static final int UNLIMITED_ATTEMPTS = Integer.MAX_VALUE;
-
- private long initialInterval = DEFAULT_INITIAL_INTERVAL;
-
- private double multiplier = DEFAULT_MULTIPLIER;
-
- private long maxInterval = DEFAULT_MAX_INTERVAL;
-
- private int maxAttempt = UNLIMITED_ATTEMPTS;
-
- /**
- * Create an instance with the default settings.
- *
- * @see #DEFAULT_INITIAL_INTERVAL
- * @see #DEFAULT_MULTIPLIER
- * @see #DEFAULT_MAX_INTERVAL
- */
- public ExponentialBackoff() {
- }
-
- /**
- * Create an instance.
- *
- * @param maxAttempt the maximum number of attempt
- */
- public ExponentialBackoff(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Create an instance with the supplied settings.
- *
- * @param initialInterval the initial interval in milliseconds
- */
- public ExponentialBackoff(long initialInterval) {
- this.initialInterval = initialInterval;
- this.checkInterval(this.initialInterval, this.maxInterval);
- }
-
- /**
- * Create an instance with the supplied settings.
- *
- * @param initialInterval the initial interval
- * @param timeUnit the initial interval's time unit
- * @param multiplier the multiplier (should be greater than or equal to 1)
- */
- public ExponentialBackoff(long initialInterval, TimeUnit timeUnit, double multiplier) {
- checkMultiplier(multiplier);
- this.multiplier = multiplier;
- this.initialInterval = BackoffExecution.DEFAULT_TIME_UNIT.convert(initialInterval, timeUnit);
- this.checkInterval(this.initialInterval, this.maxInterval);
- }
-
- public ExponentialBackoff(long initialInterval, long maxInterval, TimeUnit timeUnit, double multiplier) {
- checkMultiplier(multiplier);
- this.multiplier = multiplier;
- this.initialInterval = BackoffExecution.DEFAULT_TIME_UNIT.convert(initialInterval, timeUnit);
- this.maxInterval = BackoffExecution.DEFAULT_TIME_UNIT.convert(maxInterval, timeUnit);
- this.checkInterval(this.initialInterval, this.maxInterval);
- }
-
- /**
- * The initial interval in milliseconds.
- */
- public void setInitialInterval(long initialInterval) {
- this.initialInterval = initialInterval;
- this.checkInterval(this.initialInterval, this.maxInterval);
- }
-
- /**
- * Return the initial interval in milliseconds.
- */
- public long getInitialInterval() {
- return initialInterval;
- }
-
- /**
- * The value to multiply the current interval by for each retry attempt.
- */
- public void setMultiplier(double multiplier) {
- checkMultiplier(multiplier);
- this.multiplier = multiplier;
- }
-
- /**
- * Return the value to multiply the current interval by for each retry attempt.
- */
- public double getMultiplier() {
- return multiplier;
- }
-
- /**
- * The maximum back off time.
- */
- public void setMaxInterval(long maxInterval) {
- this.maxInterval = maxInterval;
- }
-
- /**
- * Return the maximum back off time.
- */
- public long getMaxInterval() {
- return maxInterval;
- }
-
- /**
- * Set the maximum number of attempt in milliseconds.
- */
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Return the maximum number of attempt in milliseconds.
- */
- public int getMaxAttempt() {
- return maxAttempt;
- }
-
- @Override
- public BackoffExecution start() {
- return new ExponentialBackoffExecution(initialInterval, maxInterval, multiplier, maxAttempt);
- }
-
- private void checkMultiplier(double multiplier) {
- if (multiplier < 1) {
- throw new IllegalArgumentException("Invalid multiplier '" + multiplier + "'. Should be equal" +
- "or higher than 1. A multiplier of 1 is equivalent to a fixed interval");
- }
- }
-
- private void checkInterval(long initialInterval, long maxInterval) {
- if (initialInterval <= 0) {
- throw new IllegalArgumentException("Invalid initialInterval '" + initialInterval + "'. Should be higher" +
- " than 0. A initialInterval of 0 is equivalent to no interval");
- }
- if (maxInterval <= initialInterval * getMultiplier()) {
- throw new IllegalArgumentException("Invalid maxInterval '" + maxInterval + "'. Should be higher" +
- " than initialInterval * multiplier. A maxInterval equal or less than initialInterval * multiplier " +
- "is equivalent to a fixed interval");
- }
- }
-
- public static class ExponentialBackoffExecution implements BackoffExecution, Serializable {
-
- private static final long serialVersionUID = 672748521748221970L;
-
- private long initialInterval;
-
- private double multiplier;
-
- private long maxInterval;
-
- private int maxAttempt;
-
- private long currentInterval = -1;
-
- private long currentElapsedTime = 0;
-
- private int currentAttempt = 0;
-
- public ExponentialBackoffExecution() {
- this(DEFAULT_INITIAL_INTERVAL, DEFAULT_MAX_INTERVAL, DEFAULT_MULTIPLIER, UNLIMITED_ATTEMPTS);
- }
-
- public ExponentialBackoffExecution(long initialInterval, long maxInterval, double multiplier, int maxAttempt) {
- this.initialInterval = initialInterval;
- this.maxInterval = maxInterval;
- this.multiplier = multiplier;
- this.maxAttempt = maxAttempt;
- }
-
- @Override
- public int currentAttempt() {
- return currentAttempt;
- }
-
- @Override
- public long getElapsedTime() {
- return this.currentElapsedTime;
- }
-
- @Override
- public long nextBackoff() {
-
- if (currentAttempt >= maxAttempt) {
- return STOP;
- }
-
- long nextInterval = computeNextInterval();
- this.currentElapsedTime += nextInterval;
- this.currentAttempt += 1;
- return nextInterval;
- }
-
- private long computeNextInterval() {
- long maxInterval = this.maxInterval;
- if (this.currentInterval >= maxInterval) {
- return maxInterval;
- } else if (this.currentInterval < 0) {
- this.currentInterval = this.initialInterval;
- } else {
- this.currentInterval = multiplyInterval(this.currentInterval, maxInterval);
- }
- return this.currentInterval;
- }
-
- private long multiplyInterval(long currentInterval, long maxInterval) {
- long interval = currentInterval;
- interval *= this.multiplier;
- return (interval > maxInterval ? maxInterval : interval);
- }
-
- @Override
- public void updateCurrentAttempt(int attempt) {
- if (attempt < 0) {
- this.currentAttempt = 0;
- } else if (attempt >= maxAttempt) {
- this.currentAttempt = maxAttempt;
- } else {
- this.currentAttempt = attempt;
- }
- this.currentElapsedTime = this.getElapsedTime(this.currentAttempt);
- }
-
- @Override
- public long getBackoff(int attempt) {
- if (attempt <= 0) {
- return 0L;
- }
-
- if (attempt - 1 >= maxAttempt) {
- return STOP;
- }
-
- long interval = this.initialInterval;
- long maxInterval = this.maxInterval;
- for (long i = 1; i < attempt; i++) {
- interval = multiplyInterval(interval, maxInterval);
- if (interval >= maxInterval) {
- break;
- }
- }
- return interval;
- }
-
- @Override
- public long getElapsedTime(int attempt) {
- if (attempt >= maxAttempt) {
- attempt = maxAttempt;
- }
- long interval = this.initialInterval;
- long maxInterval = this.maxInterval;
- long elapsedTime = 0;
- if (attempt <= 0) {
- return elapsedTime;
- } else {
- elapsedTime = interval;
- }
-
- for (long i = 1; i < attempt; i++) {
- if (interval < maxInterval) {
- interval = multiplyInterval(interval, maxInterval);
- }
- elapsedTime += interval;
- }
- return elapsedTime;
- }
-
- public long getInitialInterval() {
- return initialInterval;
- }
-
- public void setInitialInterval(long initialInterval) {
- this.initialInterval = initialInterval;
- }
-
- public double getMultiplier() {
- return multiplier;
- }
-
- public void setMultiplier(double multiplier) {
- this.multiplier = multiplier;
- }
-
- public long getMaxInterval() {
- return maxInterval;
- }
-
- public void setMaxInterval(long maxInterval) {
- this.maxInterval = maxInterval;
- }
-
- @Override
- public int getMaxAttempt() {
- return maxAttempt;
- }
- @Override
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- public long getCurrentInterval() {
- return currentInterval;
- }
-
- public void setCurrentInterval(long currentInterval) {
- this.currentInterval = currentInterval;
- }
-
- public long getCurrentElapsedTime() {
- return currentElapsedTime;
- }
-
- public void setCurrentElapsedTime(long currentElapsedTime) {
- this.currentElapsedTime = currentElapsedTime;
- }
-
- public int getCurrentAttempt() {
- return currentAttempt;
- }
-
- public void setCurrentAttempt(int currentAttempt) {
- this.currentAttempt = currentAttempt;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder("ExponentialBackOff{");
- sb.append("currentInterval=").append(this.currentInterval < 0 ? "n/a" : this.currentInterval + "ms");
- sb.append(", multiplier=").append(this.multiplier);
- sb.append('}');
- return sb.toString();
- }
- }
-
- }
- package com.xxx.commons.retry.backoff;
-
- import java.io.Serializable;
- import java.util.concurrent.TimeUnit;
-
- /**
- * @created 2021-12-20 4:32 PM
- * @description:
- */
- public class FixedBackoff implements Backoff, Serializable {
-
- private static final long serialVersionUID = 2511140811757045231L;
-
- /**
- * The default recovery interval: 5000 ms = 5 seconds.
- */
- public static final long DEFAULT_INTERVAL = 5000L;
-
- /**
- * Constant value indicating an unlimited number of attempt.
- */
- public static final int UNLIMITED_ATTEMPTS = Integer.MAX_VALUE;
-
- private long interval = DEFAULT_INTERVAL;
-
- private int maxAttempt = UNLIMITED_ATTEMPTS;
-
-
- /**
- * Create an instance with an interval of {@value #DEFAULT_INTERVAL}
- * ms and an unlimited number of attempt.
- */
- public FixedBackoff() {
- }
-
-
- /**
- * Create an instance.
- *
- * @param maxAttempt the maximum number of attempt
- */
- public FixedBackoff(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Create an instance.
- *
- * @param interval the interval between two attempt
- * @param timeUnit the time unit of interval
- */
- public FixedBackoff(long interval, TimeUnit timeUnit) {
- this.interval = BackoffExecution.DEFAULT_TIME_UNIT.convert(interval, timeUnit);
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Create an instance.
- *
- * @param maxAttempt the maximum number of attempt
- * @param interval the interval between two attempt
- */
- public FixedBackoff(int maxAttempt, long interval) {
- this.interval = interval;
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Create an instance.
- *
- * @param maxAttempt the maximum number of attempt
- * @param interval the interval between two attempt
- * @param timeUnit the time unit of interval
- */
- public FixedBackoff(int maxAttempt, long interval, TimeUnit timeUnit) {
- this.interval = BackoffExecution.DEFAULT_TIME_UNIT.convert(interval, timeUnit);
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Set the interval between two attempt in milliseconds.
- */
- public void setInterval(long interval) {
- this.interval = interval;
- }
-
- /**
- * Return the interval between two attempt in milliseconds.
- */
- public long getInterval() {
- return interval;
- }
-
- /**
- * Set the maximum number of attempt in milliseconds.
- */
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Return the maximum number of attempt in milliseconds.
- */
- public int getMaxAttempt() {
- return maxAttempt;
- }
-
-
- @Override
- public BackoffExecution start() {
- return new FixedBackoffExecution(interval, maxAttempt);
- }
-
-
- public static class FixedBackoffExecution implements BackoffExecution, Serializable {
-
- private static final long serialVersionUID = 1656175761226107038L;
-
- private long interval;
-
- private int maxAttempt;
-
- private int currentAttempt = 0;
- private long currentElapsedTime = 0;
-
- public FixedBackoffExecution() {
- this(DEFAULT_INTERVAL, UNLIMITED_ATTEMPTS);
- }
-
- public FixedBackoffExecution(long interval, int maxAttempt) {
- this.interval = interval;
- this.maxAttempt = maxAttempt;
- }
-
- public long getInterval() {
- return interval;
- }
-
- public void setInterval(long interval) {
- this.interval = interval;
- }
-
- @Override
- public int getMaxAttempt() {
- return maxAttempt;
- }
- @Override
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- public int getCurrentAttempt() {
- return currentAttempt;
- }
-
- public void setCurrentAttempt(int currentAttempt) {
- this.currentAttempt = currentAttempt;
- }
-
- public long getCurrentElapsedTime() {
- return currentElapsedTime;
- }
-
- public void setCurrentElapsedTime(long currentElapsedTime) {
- this.currentElapsedTime = currentElapsedTime;
- }
-
- @Override
- public int currentAttempt() {
- return currentAttempt;
- }
-
- @Override
- public long getElapsedTime() {
- return this.currentElapsedTime;
- }
-
- @Override
- public long nextBackoff() {
- if (this.currentAttempt < this.maxAttempt) {
- long nextInterval = this.interval;
- this.currentElapsedTime += nextInterval;
- this.currentAttempt++;
- return nextInterval;
- } else {
- return STOP;
- }
- }
-
- @Override
- public void updateCurrentAttempt(int attempt) {
- if (attempt < 0) {
- this.currentAttempt = 0;
- } else if (attempt >= maxAttempt) {
- this.currentAttempt = maxAttempt;
- } else {
- this.currentAttempt = attempt;
- }
- this.currentElapsedTime = this.getElapsedTime(this.currentAttempt);
- }
-
- @Override
- public long getBackoff(int attempt) {
- if (attempt <= 0) {
- return 0L;
- }
-
- if (attempt - 1 >= maxAttempt) {
- return STOP;
- }
-
- return this.interval;
- }
-
- @Override
- public long getElapsedTime(int attempt) {
- return this.interval * attempt;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("FixedBackoff{");
- sb.append("interval=").append(this.interval);
- String attemptValue = (this.maxAttempt == Integer.MAX_VALUE ?
- "unlimited" : String.valueOf(this.maxAttempt));
- sb.append(", maxAttempt=").append(attemptValue);
- sb.append(", currentAttempt=").append(this.currentAttempt);
- sb.append('}');
- return sb.toString();
- }
- }
-
- }
-
- package com.xxx.commons.retry.backoff;
-
- import java.io.Serializable;
- import java.util.concurrent.TimeUnit;
-
- import static com.xxx.commons.retry.backoff.BackoffExecution.DEFAULT_TIME_UNIT;
-
-
- /**
- * @created 2021-12-20 4:33 PM
- * @description:
- */
- public class GradualBackoff implements Backoff, Serializable {
-
- private static final long serialVersionUID = -4082336395861849848L;
-
- /**
- * The default initial interval.
- */
- public static final long DEFAULT_INITIAL_INTERVAL = 2000L;
-
- /**
- * The default recovery interval: 3000 ms = 3 seconds.
- */
- public static final long DEFAULT_INTERVAL = 3000L;
-
- /**
- * Constant value indicating an unlimited number of attempt.
- */
- public static final int UNLIMITED_ATTEMPTS = Integer.MAX_VALUE;
-
- private long initialInterval = DEFAULT_INITIAL_INTERVAL;
-
- private long interval = DEFAULT_INTERVAL;
-
- private int maxAttempt = UNLIMITED_ATTEMPTS;
-
-
- /**
- * Create an instance with an interval of {@value #DEFAULT_INTERVAL}
- * ms and an unlimited number of attempt.
- */
- public GradualBackoff() {
- }
-
-
- /**
- * Create an instance.
- *
- * @param maxAttempt the maximum number of attempt
- */
- public GradualBackoff(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Create an instance.
- *
- * @param interval the interval between two attempt
- * @param timeUnit the time unit of interval
- */
- public GradualBackoff(long initialInterval, long interval, TimeUnit timeUnit) {
- this.initialInterval = DEFAULT_TIME_UNIT.convert(initialInterval, timeUnit);
- this.interval = DEFAULT_TIME_UNIT.convert(interval, timeUnit);
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Create an instance.
- *
- * @param maxAttempt the maximum number of attempt
- * @param interval the interval between two attempt
- */
- public GradualBackoff(int maxAttempt, long initialInterval, long interval) {
- this.initialInterval = initialInterval;
- this.interval = interval;
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Create an instance.
- *
- * @param maxAttempt the maximum number of attempt
- * @param interval the interval between two attempt
- * @param timeUnit the time unit of interval
- */
- public GradualBackoff(int maxAttempt, long initialInterval, long interval, TimeUnit timeUnit) {
- this.initialInterval = DEFAULT_TIME_UNIT.convert(initialInterval, timeUnit);
- this.interval = DEFAULT_TIME_UNIT.convert(interval, timeUnit);
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Return the interval of first attempt in milliseconds.
- *
- * @return
- */
- public long getInitialInterval() {
- return initialInterval;
- }
-
- /**
- * Set the interval of first attempt in milliseconds.
- */
- public void setInitialInterval(long initialInterval) {
- this.initialInterval = initialInterval;
- }
-
- /**
- * Set the interval between two attempt in milliseconds.
- */
- public void setInterval(long interval) {
- this.interval = interval;
- }
-
- /**
- * Return the interval between two attempt in milliseconds.
- */
- public long getInterval() {
- return interval;
- }
-
- /**
- * Set the maximum number of attempt in milliseconds.
- */
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Return the maximum number of attempt in milliseconds.
- */
- public int getMaxAttempt() {
- return maxAttempt;
- }
-
- @Override
- public BackoffExecution start() {
- return new GradualBackoffExecution(initialInterval, interval, maxAttempt);
- }
-
- public static class GradualBackoffExecution implements BackoffExecution, Serializable {
-
- private static final long serialVersionUID = 6691539566098442985L;
-
- private long initialInterval;
-
- private long interval;
-
- private int maxAttempt;
-
- private int currentAttempt = 0;
- private long currentElapsedTime = 0;
-
- public GradualBackoffExecution() {
- this(DEFAULT_INITIAL_INTERVAL, DEFAULT_INTERVAL, UNLIMITED_ATTEMPTS);
- }
-
- public GradualBackoffExecution(long initialInterval, long interval, int maxAttempt) {
- this.initialInterval = initialInterval;
- this.interval = interval;
- this.maxAttempt = maxAttempt;
- }
-
- @Override
- public int currentAttempt() {
- return currentAttempt;
- }
-
- @Override
- public long getElapsedTime() {
- return this.currentElapsedTime;
- }
-
- @Override
- public long nextBackoff() {
- if (this.currentAttempt < this.maxAttempt) {
- long nextInterval = this.currentAttempt == 0 ? this.initialInterval : this.interval;
- this.currentElapsedTime += nextInterval;
- this.currentAttempt++;
- return nextInterval;
- } else {
- return STOP;
- }
- }
-
- @Override
- public void updateCurrentAttempt(int attempt) {
- if (attempt < 0) {
- this.currentAttempt = 0;
- } else if (attempt >= maxAttempt) {
- this.currentAttempt = maxAttempt;
- } else {
- this.currentAttempt = attempt;
- }
- this.currentElapsedTime = this.getElapsedTime(this.currentAttempt);
- }
-
- @Override
- public long getBackoff(int attempt) {
- if (attempt <= 0) {
- return 0L;
- }
-
- if (attempt - 1 >= maxAttempt) {
- return STOP;
- }
-
- return attempt == 1 ? this.initialInterval : this.interval;
- }
-
- @Override
- public long getElapsedTime(int attempt) {
- return attempt == 1 ? this.initialInterval : this.initialInterval + this.interval * (attempt - 1);
- }
-
- public long getInitialInterval() {
- return initialInterval;
- }
-
- public void setInitialInterval(long initialInterval) {
- this.initialInterval = initialInterval;
- }
-
- public long getInterval() {
- return interval;
- }
-
- public void setInterval(long interval) {
- this.interval = interval;
- }
-
- @Override
- public int getMaxAttempt() {
- return maxAttempt;
- }
- @Override
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- public int getCurrentAttempt() {
- return currentAttempt;
- }
-
- public void setCurrentAttempt(int currentAttempt) {
- this.currentAttempt = currentAttempt;
- }
-
- public long getCurrentElapsedTime() {
- return currentElapsedTime;
- }
-
- public void setCurrentElapsedTime(long currentElapsedTime) {
- this.currentElapsedTime = currentElapsedTime;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("GradualBackoff{");
- sb.append("initialInterval=").append(this.initialInterval);
- sb.append("interval=").append(this.interval);
- String attemptValue = (this.maxAttempt == Integer.MAX_VALUE ?
- "unlimited" : String.valueOf(this.maxAttempt));
- sb.append(", maxAttempt=").append(attemptValue);
- sb.append(", currentAttempt=").append(this.currentAttempt);
- sb.append('}');
- return sb.toString();
- }
- }
-
- }
-
- package com.xxx.commons.retry.backoff;
-
- import java.io.Serializable;
-
- /**
- * @created 2021-12-20 4:34 PM
- * @description:
- */
- public class NoneBackoff implements Backoff, Serializable {
-
- private static final long serialVersionUID = 8227959838869099892L;
-
- /**
- * The default recovery interval: 0 ms = 0 seconds.
- */
- public static final long DEFAULT_INTERVAL = 0L;
-
- /**
- * Constant value indicating an unlimited number of attempt.
- */
- public static final int UNLIMITED_ATTEMPTS = Integer.MAX_VALUE;
-
- private long interval = DEFAULT_INTERVAL;
-
- private int maxAttempt = UNLIMITED_ATTEMPTS;
-
-
- /**
- * Create an instance with an interval of {@value #DEFAULT_INTERVAL}
- * ms and an unlimited number of attempt.
- */
- public NoneBackoff() {
- }
-
- /**
- * Create an instance.
- *
- * @param maxAttempt the maximum number of attempt
- */
- public NoneBackoff(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- /**
- * Return the interval between two attempt in milliseconds.
- */
- public long getInterval() {
- return interval;
- }
-
- /**
- * Return the maximum number of attempt in milliseconds.
- */
- public int getMaxAttempt() {
- return maxAttempt;
- }
-
- /**
- * Set the maximum number of attempt in milliseconds.
- */
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- @Override
- public BackoffExecution start() {
- return new NoneBackoffExecution(interval, maxAttempt);
- }
-
-
- public static class NoneBackoffExecution implements BackoffExecution, Serializable {
-
- private static final long serialVersionUID = 2453613900451888865L;
-
- private long interval;
-
- private int maxAttempt;
-
- private int currentAttempt = 0;
- private long currentElapsedTime = 0;
-
- public NoneBackoffExecution() {
- this(DEFAULT_INTERVAL, UNLIMITED_ATTEMPTS);
- }
-
- public NoneBackoffExecution(long interval, int maxAttempt) {
- this.interval = interval;
- this.maxAttempt = maxAttempt;
- }
-
- @Override
- public int currentAttempt() {
- return currentAttempt;
- }
-
- @Override
- public long getElapsedTime() {
- return this.currentElapsedTime;
- }
-
- @Override
- public long nextBackoff() {
- if (this.currentAttempt < this.maxAttempt) {
- long nextInterval = this.interval;
- this.currentElapsedTime += nextInterval;
- this.currentAttempt++;
- return nextInterval;
- } else {
- return STOP;
- }
- }
-
- @Override
- public void updateCurrentAttempt(int attempt) {
- if (attempt < 0) {
- this.currentAttempt = 0;
- } else if (attempt >= maxAttempt) {
- this.currentAttempt = maxAttempt;
- } else {
- this.currentAttempt = attempt;
- }
- this.currentElapsedTime = this.getElapsedTime(this.currentAttempt);
- }
-
- @Override
- public long getBackoff(int attempt) {
- if (attempt <= 0) {
- return 0L;
- }
-
- if (attempt - 1 >= maxAttempt) {
- return STOP;
- }
-
- return this.interval;
- }
-
- @Override
- public long getElapsedTime(int attempt) {
- return this.interval * attempt;
- }
-
- public long getInterval() {
- return interval;
- }
-
- public void setInterval(long interval) {
- this.interval = interval;
- }
-
- @Override
- public int getMaxAttempt() {
- return maxAttempt;
- }
- @Override
- public void setMaxAttempt(int maxAttempt) {
- this.maxAttempt = maxAttempt;
- }
-
- public int getCurrentAttempt() {
- return currentAttempt;
- }
-
- public void setCurrentAttempt(int currentAttempt) {
- this.currentAttempt = currentAttempt;
- }
-
- public long getCurrentElapsedTime() {
- return currentElapsedTime;
- }
-
- public void setCurrentElapsedTime(long currentElapsedTime) {
- this.currentElapsedTime = currentElapsedTime;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("NoneBackoff{");
- sb.append("interval=").append(this.interval);
- sb.append(", maxAttempt=").append(this.maxAttempt);
- sb.append('}');
- return sb.toString();
- }
- }
- }
-
网关使用示例:
添加依赖
- <!-- 公共模块 -->
- <dependency>
- <groupId>com.xxx.arch</groupId>
- <artifactId>xxx-commons-recipes</artifactId>
- <version>1.0.8</version>
- <!-- <version>${xxx.commons.version}</version> -->
- </dependency>
初始化
- @Configuration
- @AutoConfigureAfter(OnsConfig.class)
- public class LinkBean {
-
- public static final String MESSAGE_DELAY_LEVEL = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";
-
- @Bean
- public BackoffExecution backoffExecution() {
- return new CustomBackoff(MESSAGE_DELAY_LEVEL, MAX_RETRY_COUNT).start();
- }
-
- ...
- }
具体使用
- @Slf4j
- public class RetryFilterFactory implements FilterFactory {
- private Producer producer;
- private BackoffExecution backoffExecution;
-
- public RetryFilterFactory(Producer producer, BackoffExecution backoffExecution) {
- this.producer = producer;
- this.backoffExecution = backoffExecution;
- }
-
- @Override
- public String name() {
- return "retry";
- }
-
- @Override
- public Filter apply(Properties properties) {
-
- return (context, chain) -> {
-
- int retry = context.getRetryCount();
- retry++;
-
- long retryTime = context.getAttributeOrDefault(LinkContext.FAILOVER_RETRY_TIME_ATTRIBUTE, 0L);
- context.getAttributes().put(LinkContext.FAILOVER_RETRY_TIME_ATTRIBUTE,
- retryTime + backoffExecution.getBackoff(retry));
-
- try {
- producer.send(context);
- } catch (Exception exp) {
- log.error("master send context: {}, error:", context, exp);
- throw new LinkIOException("send master mq error");
- }
- chain.filter(context);
- };
- }
- }
希望大家一起来共建xxx-commons组件,也希望xxx-commons组件能够成为内部基础组件被广泛使用,提升系统和业务开发效率,并提升开发质量。