DevJong12

[Picasso][Spring]Scheduler와 Mail서비스 그리고 장애 본문

프로젝트/Picasso

[Picasso][Spring]Scheduler와 Mail서비스 그리고 장애

Jong12 2023. 10. 3. 00:10
728x90

목차

    💡해당 페이지에서 모든 메일 실행 로직에 대해서는 Thread.sleep(500)으로 대체하였다.
    이유는 메일을 발송함에 있어 한계가 존재하나, 실제 걸리는 시간은 약 500ms~1000ms로 확인하였기 떄문에, 성능 테스트에까지 굳이 메일 API를 확인할 필요는 없다고 판단하였다.
    💡메소드는 스케쥴러 메소드 한개만을 기준으로 작업을 진행하였다.

    개요

    아래의 게시물에서 지난번에 MailService와 연결한 코드를 볼 수 있다.
    메일서비스와 연계하면서 메일 시간에 대해서 측정을 하고 보니, 많은 양의 게시물의 상태값을 변경하고자 하면 너무나도 오랜시간을 Scheduler메소드가 잡혀있으면서, 상태값이 변경되지 않는 문제를 장애로 인식을 해볼 수 있게 되었다.

     

     

    [Picasso][Spring] @Scheduled를 통한 경매 상태 변경

    개요 💡해당 게시물은 Scheduled API를 뜯어보는 게시물이 아니다. 필자가 필요한 만큼만 활용을 하였다. 프로젝트를 제작함에 있어서, 올라온 게시물이 경매시작일인 경우 경매를 시작하거나 유

    devjong12.tistory.com


    기존코드의 실행 로직

    다음과 같이 스케쥴러에서 forEach로 sendMailService의 Method를 호출한다.
    @Transactional
    @Scheduled(cron = "0 0 9 * * *", zone = DateStaticConstants.ZONE_SEOUL)
    public void startApprovePictureToBiddingAuction() {
        log.info("Start Todays Auctions Open Schedule Runtime : NowTime >>> {}", LocalDateTime.now());
        pictureService
                .changePictureStatusByPictureStatusAndBidStartDate(AFTER_APPROVE, BIDDING, LocalDate.now())
                .forEach(sendMailService::startBiddingMail);
        log.info("End Todays Auctions Open Schedule Runtime : NowTime >>> {}", LocalDateTime.now());
    }

     

    public void startBiddingMail(Picture picture) {
        sendMailUtil.sendMail(
                picture.getUser().getEmail(),
                BIDDING.getMailTitle(),
                PICTURE_BIDDING_MAIL,
                new HashMap<>() {{
                    put("pictureName", picture.getPictureName());
                    put("bidEndDate", picture.getBidEndDate().toString());
                    put("link", picassoProperties.getDomain() + "pictures/" + picture.getPictureId());
                }}
        );
    }

    기존코드의 실행 결과

    작업해야 하는 데이터를 100건이라고 가정해 보겠다, 실제 샘플데이터를 100건을 준비하였으며 메일은 Thread.sleep(500)으로 대체되었다. 

    이 경우 100건 * 0.5초 이기때문에 50초의 시간이 소요된 이후 게시물이 업데이트가 진행되게 된다
    두번쨰와 세번째의 사진을 보면 실행시작 시간이 자세히 보면 16:46:00에 스케쥴러가 시작해서 16:49:50에 종료가 되는 것을 볼 수가 있다. 즉 50초의 시간동안 경매가 시작하지 않는 장애가 발생하게 되는 것이다.


    해결 방법?

    필자의 경우에는 Mail의 실행 결과가 굳이 불필요 했다. 그렇기에 비동기로 해당 문제를 풀어보고자 했다.
    스케쥴러를 실행할때 메일은 비동기로 결과여부를 신경쓰지 않고 메소드가 종료되고 트랜잭션이 끝내게 처리할 수 있으면 된다고 판단하였다.

    필요 설정

    @EnableAsync어노테이션의 추가가 필요하다. Configuration으로 추가를 해줘도 된다.
    @EnableAsync
    @SpringBootApplication
    @RequiredArgsConstructor
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

    코드의 변경점

    메일 로직에서 @Async어노테이션을 통해 비동기로 메소드가 실행된다는 것을 인지시켜 줬다.
    @Async
    public void startBiddingMail(Picture picture) {
        sendMailUtil.sendMail(
                picture.getUser().getEmail(),
                BIDDING.getMailTitle(),
                PICTURE_BIDDING_MAIL,
                new HashMap<>() {{
                    put("pictureName", picture.getPictureName());
                    put("bidEndDate", picture.getBidEndDate().toString());
                    put("link", picassoProperties.getDomain() + "pictures/" + picture.getPictureId());
                }}
        );
    }

    변경 후 결과

    이번에는 작업하는 데이터의 량을 많이 늘려 2200건정도를 준비하였다.

    2200건을 h2에 삽입후 처리해본 결과 실제 시간이 0초가 걸리는 결과를 볼 수가 있다.. 헤헤...


    글을 정리하며

    정말...너무 재밌었다... 이런 오류, 장애를 해결하는 과정... 그리고 실제 접해볼 수 있는 문제를 내가 알고있는 CS지식을 바탕으로 해결을 하고나니 정말 여태 고생한게 헛된게 아니라는걸 다시금 느낄 수 있던 시간이었던 것 같다..흑흑
    728x90
    Comments