참고 링크
-
배경 및 목적
-
요즘 MSA 등의 형태로 서비스를 만들다보니 외부 API호출하는 경우가 많음(또는 AWS 서비스 호출)
-
네트웤 문제나 스로틀링 등의 문제로 가끔 실패가 발생하는 경우가 있음. 실패가 발생할 경우 재 처리가 필요하여 사용
예제 소스 (from AWS)
-
지수 백오프의 기본 아이디어는 오류 응답이 연이어 나올 때마다 재시도 간 대기 시간을 점진적으로 늘린다는 것.
-
최대 지연 간격과 최대 재시도 횟수를 구현해야 함. 최대 지연 시간 간격과 최대 재시도 횟수는 고정 값일 필요가 없으며, 수행 중인 작업과 다른 로컬 요인(예: 네트워크 지연 시간)을 기반으로 설정
java 버전의 재 시도 대기시간 구하는 메소드 샘플
* 참고로 jitter를 적용하는게 좋음(위 aws글 참고
Thread.sleep(RetryUtil.getRetrySleepTime(retryCnt, 2, 1000, 2000)); //대기처리
/**
* 재 시도시 대기시간(sleep) 구하기
* - 지수 백오프 알고리즘 기반
*
* @param retryCount 요청하는 재시도 횟수
* @param increaseBase 증가 처리의 지수의 밑(ex. 2^4 에서 2)
* @param increaseMillis 매 재 요청마다 증가하는 시간(밀리시간초)
* @param maxWaitMillis 최대 대기시간(밀리시간초). 매 증가하는 대기 시간은 최대 대기시간을 넘을 수 없음
* @return
*/
public static long getRetrySleepTime(int retryCount, double increaseBase, long increaseMillis, long maxWaitMillis) {
long waitTime = ((long)Math.pow(increaseBase, retryCount) * increaseMillis); //ex) ((long)Math.pow(2, retryCount) * 100L); => 100, 200, 400, 800, 1600과 같이 증가함
return Math.min(waitTime, maxWaitMillis); //두번째 argment은 최대 대기시간(밀리세컨드)
}
AWS 샘플 소스
public enum Results {
SUCCESS,
NOT_READY,
THROTTLED,
SERVER_ERROR
}
/*
* Performs an asynchronous operation, then polls for the result of the
* operation using an incremental delay.
*/
public static void doOperationAndWaitForResult() {
try {
// Do some asynchronous operation.
long token = asyncOperation();
int retries = 0;
boolean retry = false;
do {
long waitTime = Math.min(getWaitTimeExp(retries), MAX_WAIT_INTERVAL);
System.out.print(waitTime + "\n");
// Wait for the result.
Thread.sleep(waitTime);
// Get the result of the asynchronous operation.
Results result = getAsyncOperationResult(token);
if (Results.SUCCESS == result) {
retry = false;
} else if (Results.NOT_READY == result) {
retry = true;
} else if (Results.THROTTLED == result) {
retry = true;
} else if (Results.SERVER_ERROR == result) {
retry = true;
}
else {
// Some other error occurred, so stop calling the API.
retry = false;
}
} while (retry && (retries++ < MAX_RETRIES));
}
catch (Exception ex) {
}
}
/*
* Returns the next wait interval, in milliseconds, using an exponential
* backoff algorithm.
*/
public static long getWaitTimeExp(int retryCount) {
long waitTime = ((long) Math.pow(2, retryCount) * 100L);
return waitTime;
}