-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refacator: API 의존성 관리 로직 개선 #910
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
카키 고생하셨어요! 깔끔하게 구현해주셨네요👍 덕분에 레디스와 서킷 브레이커 패턴 학습할 수 있었어요.
다른 분들은 어느 정도 TTL이 적절하다고 생각하시나요 ?
3시간 쿨타임도 합리적이라고 생각해요. 근데 딱 3시간이라는 기준의 근거가 궁금하네요🤔
전 가능하다면, 동적으로 쿨타임을 정하면 좋을 것 같아요.
가장 짧은 갱신 주기인 오디세이에 맞춰, 당일 23:59:59까지 쿨타임이 적용되도록요.
public void recordFailCountInMinutes(RouteClient routeClient) { | ||
String failClientKey = RouteClientKey.getFailKey(routeClient); | ||
int failCount = redisTemplate.increment(failClientKey); | ||
redisTemplate.expire(failClientKey, FAIL_MINUTES_TTL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[질문]
실패 카운트가 될 때마다, FAIL TTL이 갱신되는 구조로 보여요. 매번 갱신하는 이유가 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
30분 내에 3번의 에러가 발생했을 때에만 격리 시키는 것을 의도했습니다!
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class CustomRedisTemplate extends RedisTemplate<String, String> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[질문]
value는 Integer 타입이어도 될 것 같은데, String으로 한 이유가 있나요?
increment
, getKeyCount
메서드는 범용적으로 사용되긴 어려울 것 같아요.
[제안]
CustomRedisTemplate
보다 RouteClientRedisTemplate
처럼 더 구체화 하는건 어떤가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redis에 모든 값들이 String으로 저장되어 형변환 없이 String으로 가져온 뒤 원하는 타입으로 변경하도록 의도했습니다!
카운팅, 카운트 조회 기능이 다른 도메인에서도 사용될 여지가 있다고 생각했었는데
각 도메인마다 가져오고 싶은 타입이 다를 수 있으니 구체화해도 좋을것 같네요!
} | ||
|
||
private void block(String blockKey) { | ||
redisTemplate.opsForValue().set(blockKey, "1"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[제안]
1
도 상수로 빼면 더 좋을 것 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BLOCK
으로 상수화했습니다!
} | ||
|
||
private void clearFailCount(String failCountKey) { | ||
redisTemplate.unlink(failCountKey); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unlink
이런것도 있었네요! delete
와 달리 비동기로 삭제되군요
routeClientCircuitBreaker.recordFailCountInMinutes(routeClient); | ||
routeClientCircuitBreaker.determineBlock(routeClient); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[제안]
서버 에러인 경우만 실패 카운트를 기록하는 게 더 좋을 것 같아요.
해당 스코프로 들어오는게 클라이언트 에러가 될 가능성도 있습니다. (ex. Dto에서 수도권 검증에 통과한 위경도 좌표가, 오디세이에서는 지원하지 않는 좌표일 수 있음)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재로썬 클라이언트 에러도 카운팅하고 있네요
외부 API 응답에 장애가 발생했을 때 던지는 에러인 OdyServerErrorException
를 잡아 카운팅하도록 수정했습니다!
redis: | ||
host: ody-redis-001.ody-redis.vd1e5e.apn2.cache.amazonaws.com |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[제안]
레디스도 비밀번호 설정 해주면 어떨까요? 예전 프로젝트에서 비밀번호 미설정으로 레디스 해킹당한 적이 있습니다ㅎㅎ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
비밀번호 설정이 필요할 것 같네요!
로컬 Redis 비밀번호는 도커 컴포즈 파일로 확인가능하고
dev, prod Redis 비밀번호는 노션 계정 페이지에 첨부했습니다!
redis-cli 접속 시 AUTH 비밀번호
명령어로 인증할 수 있습니다
|
||
private static final String TEST_KEY = "test"; | ||
|
||
@DisplayName("key의 counter를 증가시킨다.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[제안]
키가 없는 상황(0 -> 1), 키가 있는 상황(1 -> 2) 로직이 다른데, 둘다 검증하면 어떤가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
키가 없을 때 카운팅은 +1, 있을 때도 카운팅은 +1 이라서 같다고 생각했는데
다른 점에 대해 좀 더 설명해주실수 있을까요 ?? 😃
Boolean blocked = redisTemplate.hasKey(RouteClientKey.getBlockKey(routeClient)); | ||
|
||
assertAll( | ||
() -> assertThat(failCount).isEqualTo(0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요렇게도 가능합니다!
() -> assertThat(failCount).isEqualTo(0), | |
() -> assertThat(failCount).isZero(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 isZero()라는 메서드도 있었네요 반영완료!
route: | ||
client: | ||
cooldown: | ||
duration: 3600000 # 1시간 | ||
failure: | ||
max-count: 5 # 5회 연속 실패시 쿨다운 | ||
window: 300000 # 5분 내 실패 카운트 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[질문]
사용되고 있는 부분이 없어 보여요. 이건 어디에서 사용하고 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로퍼티로 관리하려했었는데 지금은 사용하고 있지 않아 제거했습니다!
🚩 연관 이슈
close #900
📝 작업 내용
List로 RouteClient를 관리하고 있기 때문에
첫 번째 RouteClient가 항상 실패하는 상황에서도 매번 호출 후 다음 RouteClient로 부터 요청 응답을 받는다.
이로 인해 다음과 같은 문제가 발생한다.
Redis를 도입해 에러가 발생한 요소에 TTL을 설정해 쿨다운을 적용하는 서킷 브레이커 패턴을 적용하여 아래와 같이 개선하고자 함.
로컬에서는 기존에 사용하던 MySQL과 같이 Docker Compose 파일에 redis 설정을 추가해 사용가능하도록 했습니다.
dev와 prod 환경은 AWS의 Elasticache로 Redis를 추가하여 연결해주었어요.
cache.t4g.micro
로 생성했고 저의 프로젝트 남은 기간동인 14일 동안 사용한다면 약11,250원
이 나올걸 봐서저희 지원 제한 요금인 70달러는 초과하지 않을 것 같아요
🏞️ 스크린샷 (선택)
🗣️ 리뷰 요구사항 (선택)
현재 3회 실패시 3시간의 TTL을 걸어 해당 시간동안 다른 RouteClient를 사용하도록 적용했어요
첫 번째 RouteClient인 Odsay의 경우 주로 에러를 뱉는 상황이 API 제한량(일/1,000)을 초과할 경우일텐데
일시적인 장애 문제도 고려, Google에는 하루라는 단위가 성립안됨을 고려했고
보통 위와 같은 이유로 장애가 발생하면 긴 시간동안 사용을 할 수 없어 3시간 단위로 확인할 하도록 설정했는데요
다른 분들은 어느 정도 TTL이 적절하다고 생각하시나요 ?