MSA 에서 Post Response 유저 Data N+1

유형찬·2022년 8월 19일
0

GDSC_BLOG_PROJECT

목록 보기
5/5

문제 : Member Database 와 Post Database 가 분리되었다는 가정하에서 Post에 저장된 userId 로 user정보를 가져오기 위해서 (nickname 등 ) 매번 MemberServer에 일일히 요청하게 되어Post 1개 당 유저 정보 조회 1개의 SELECT 요청이 생기게 된다. 이러한 구조가 옳은 것 일까?

  • 떠오르는 생각 AuthServer 캐싱 , Post 캐싱 을 하면 유저 정보 DB 에 접근 하는 횟수가 줄어들 것 , Post 서버 캐싱을 하면 동일 요청에 의한 AuthServer 접근이 줄어들 것

참고 자료

마이크로서비스 Schema 분리 설계 (테이블 분리, 외래키 참조관계, 조인, 데이터 정합성 보장)

현재 해결점

Member 정보 LocalCaching

publicclassMemberNicknameApiController {
privatefinalMemberService memberService;
    @ApiOperation(value = "닉네임 불러오기" , notes = "닉네임을 불러와서 다른 서비스에 바인딩 하기 위해서")
    @GetMapping("/api/memberInfo/{userId}")
    @Cacheable(key = "#userId" , cacheNames = "memberCaching")
publicMemberInfoResponseServerDto returnNickname(@PathVariable String userId){
log.info("호출");
if(memberService.getUserId(userId) ==null){
returnnull;
        }
        MemberInfoResponseServerDto memberInfo = memberService.getMemberInfo(userId);
returnmemberInfo;
    }

    @ApiOperation(value = "닉네임 불러오기" , notes = "닉네임을 불러와서 다른 서비스에 바인딩 하기 위해서")
    @GetMapping("/api/memberInfo")
    @Cacheable(cacheNames = "memberCaching")
publicList<MemberInfoResponseServerDto> returnNicknameList(){
log.info("호출");
List<MemberInfoResponseServerDto> memberInfos = memberService.getMemberInfos();
returnmemberInfos;
    }
}

Client Service 끼리 통신하기 위해 만든 API

@Service
@RequiredArgsConstructor
@Slf4j
publicclassMemberService {

privatestatic finalStringAuthServerURL= "http://localhost:8100";
publicMemberInfoResponseServerDto getNicknameImage(String userId) {
        RestTemplate restTemplate =newRestTemplate();
        MemberInfoResponseServerDto memberInfo = restTemplate.getForObject(
AuthServerURL+"/internal/member/api/memberInfo/{userId}",
                MemberInfoResponseServerDto.class, userId);
returnmemberInfo;
    }
public List<MemberInfoResponseServerDto> getNicknameImages() {
        RestTemplate restTemplate =newRestTemplate();
        MemberInfoResponseServerDto[] memberInfos = restTemplate.getForObject(
AuthServerURL+"/internal/member/api/memberInfo",
                MemberInfoResponseServerDto[].class);
assertmemberInfos !=null;
returnList.of(memberInfos);
    }

}
  • MVC 에서는 RestTemplate 를 통해서 서비스간 통신을 한다.

  • Post 글을 List로 반환 할 때 Post 마다 memberInfo 호출 하는 것은 AuthServer 에 상당한 트래픽을 요구

  • 이 경우에는 모든 memberInfo 를 가져와서 Blog서버에서 filter 처리를 하도록 하였음 ( 부하 분산을 위해서 , SELECT 문 1개)

결론

  • Member 정보 캐싱으로 불필요한 데이터베이스 접근 방지 ( user Update , insert 시 캐시 Put )
  • List 형식 MemberInfo 반환으로 쿼리 수 감소
profile
rocoli에요

0개의 댓글