practice-implement-failure-protection
✅ 장애 전파 방어 코드 작성하지 않으면 어떻게 되는 지 테스트하기
- user-service 서버 종료시키기
user-service가 장애가 났다고 가정하기 위해 user-serivce를 종료시키자.
- 게시글 조회 API로 요청 보내기
user-service가 정상적으로 작동하지 않을 때, board-service의 게시글 조회 API도 같이 장애가 나는 걸 확인할 수 있다. 즉, 장애가 전파됐다.
✅ 장애 전파 방지 전략
User Service가 장애가 나더라도 Board Service의 게시글 조회 API의 로직은 영향을 받지 않게 만들어보자. 여러 장애 전파 방지 전략 중 ‘정상적으로 응답할 수 있는 값만 사용자에게 응답하는 방식’으로 장애 전파를 막아보자.
Response
200 OK
{
"boardId": 1,
"title": "제목",
"content": "내용"
"user": null
}
✅ 코드 작성하기
board-service에서 아래 코드 작성하기
- UserClient 코드 수정하기
client/UserClient
@Component
public class UserClient {
private final RestClient restClient;
public UserClient(
@Value("${client.user-service.url}") String userServiceUrl
) {
this.restClient = RestClient.builder()
.baseUrl(userServiceUrl)
.build();
}
public Optional<UserResponseDto> fetchUser(Long userId) {
try {
UserResponseDto userResponseDto = this.restClient.get()
.uri("/users/{userId}", userId)
.retrieve()
.body(UserResponseDto.class);
return Optional.ofNullable(userResponseDto);
} catch (RestClientException e) {
// 로깅 : 예외 발생 시 로그를 남겨 문제를 파악할 수 있게 해야 함
// log.error("사용자 정보 조회 실패: {}", e.getMessage(), e);
return Optional.empty();
}
}
}
- BoardService 코드 수정하기
service/BoardService
@Service
public class BoardService {
private final BoardRepository boardRepository;
private final UserClient userClient;
public BoardService(BoardRepository boardRepository, UserClient userClient) {
this.boardRepository = boardRepository;
this.userClient = userClient;
}
...
public BoardResponseDto getBoard(Long boardId) {
// 게시글 불러오기
Board board = boardRepository.findById(boardId)
.orElseThrow(() -> new IllegalArgumentException("게시글을 찾을 수 없습니다."));
// user-service로부터 사용자 정보 불러오기
Optional<UserResponseDto> optionalUserResponseDto = userClient.fetchUser(board.getUserId());
// UserDto 생성
UserDto userDto = null;
if (optionalUserResponseDto.isPresent()) {
UserResponseDto userResponseDto = optionalUserResponseDto.get();
userDto = new UserDto(
userResponseDto.getUserId(),
userResponseDto.getName()
);
}
// ResponseDto 생성
BoardResponseDto boardResponseDto = new BoardResponseDto(
board.getBoardId(),
board.getTitle(),
board.getContent(),
userDto
);
return boardResponseDto;
}
}
- board-service와 user-service 서버 둘 다 실행시키기
- 게시글 조회 API 잘 작동하는 지 테스트해보기
- user-service 서버만 종료하기
user-service에 장애가 난 상황을 가정하기 위해 서버를 종료시키자.
- 게시글 조회 API 잘 작동하는 지 테스트해보기
분명 user-service가 정상적으로 작동하고 있지 않는 상태인데도 불구하고, board-service에는 영향을 미치지 않았다. 이로써 장애가 전파되지 않았다.