SpringBoot 는 다 중 스 레 드 를 사용 하여 RESTful 서비스의 성능 을 향상 시킨다.

1.동기 화 처리
  • 테스트 용례 작성
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class AsyncControllerTest {
    
        @Autowired
        private WebApplicationContext wac;
    
        private MockMvc mockMvc;
    
    
        @Before
        public void setUp() throws Exception {
            mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        }
    
        @Test
        public void order() throws Exception {
            mockMvc.perform(MockMvcRequestBuilders.get("/order").contentType(MediaType.APPLICATION_JSON_UTF8))
                    .andExpect(MockMvcResultMatchers.status().isOk());
        }
    }
    
  • 동기 처리 코드
    @RestController
    @RequestMapping("/order")
    @Slf4j
    public class AsyncController {
    
        @GetMapping
        public String order() throws InterruptedException {
            log.info("     ");
            Thread.sleep(1000);
            log.info("     ");
            return "success";
        }
    }
    
  • 운행 결 과 는 다음 과 같다.
  • 2.Runnable 을 사용 하여 비동기 처리
  • 코드 는 다음 과 같다.
    @GetMapping
    public Callable order() throws InterruptedException {
        log.info("     ");
        Callable result = new Callable() {
            @Override
            public String call() throws Exception {
    
                log.info("     ");
                Thread.sleep(1000);
                log.info("     ");
                return  "success";
            }
        };
        log.info("     ");
        return result;
    }
    
  • 테스트 결 과 는 다음 과 같다.메 인 스 레 드 는 거의 동시에 되 돌 아 왔 고 부 스 레 드 처리 가 끝 날 때 까지 기다 리 지 않 았 다.

  • 3.Deferred Result 로 비동기 요청 처리
    Deferred Result 를 사용 하여 비동기 요청 을 처리 하려 는 이 유 는 Runnable 방식 으로 모든 요 구 를 완전히 처리 할 수 없 기 때 문 입 니 다.
    Runnable 방식 으로 비동기 처 리 를 할 때 부 스 레 드 는 주 스 레 드 에서 조정 되 어야 합 니 다.
    실제 업무 장면 에서 수 요 를 만족 시 킬 수 없다.
  • 수요 사례(이하 단일 작업 의 경우)는 위의 그림 에서 보 여 준 업무 절차 에서 다음 요청 을 받 는 응용 과 다음 논 리 를 진정 으로 처리 하 는 응용 은 하나의 응용 이 아니 라 같은 서버 에 있 지 않다.스 레 드 1 은 http 요청 을 받 은 후 메시지 대기 열 에 요청 을 넣 고 2 가 있 는 서버 를 적용 합 니 다.다음 http 요청 이 있 는 것 을 감청 한 후 2 를 사용 하여 다음 의 논 리 를 처리 합 니 다.다음 단계 의 논리 적 처리 가 완료 되면 결 과 를 메시지 대기 열 에 배치 하고 응용 1 에 다른 스 레 드 가 있 습 니 다.스 레 드 2 는 메시지 대기 열 에 다음 단계 가 완 료 된 메 시 지 를 감청 한 후 다음 단계 의 결과 에 따라 http 응답 을 합 니 다.전체 장면 에서 스 레 드 1 과 스 레 드 2 는 완전히 격 리 된 상태 이 고 Runnable 방식 을 사용 하면 수 요 를 만족 시 킬 수 없습니다.
  • 인 코딩 디자인
  • 한 대상 을 사용 하여 메시지 대기 열 을 모 의 합 니 다.다음 요청 을 받 은 후 1 초 지연 되면 메시지 대기 열 에'주문 완료'메 시 지 를 설치 합 니 다.
  • 스 레 드 1 의 처리:
  • 스 레 드 2 의 처리 스 레 드 2 는 모니터 로 서 메시지 큐 에 주문 이 완 료 된 메 시 지 를 들 었 을 때 결 과 를 되 돌려 줍 니 다.
  • Deferred Result 는 스 레 드 1 과 스 레 드 2 사이 에 Defrred Result 대상 을 전달 해 야 스 레 드 2 에서 스 레 드 1 에서 생 성 된 Deferred Result 를 사용 하여 처리 한 결 과 를 되 돌 릴 수 있 습 니 다.

  • 인 코딩(예시 코드 는 과정 을 간소화 하기 위해 라인 탱크 를 사용 하지 않 았 다)
  • 아 날로 그 메시지 큐 대상
    @Component
    public class MockQueue {
    
        /**
         *     
         */
        private String placeOrder;
    
        /**
         *        
         */
        private String completeOrder;
    
    
        public String getPlaceOrder() {
            return placeOrder;
        }
    
        public void setPlaceOrder(String placeOrder)  {
    		
            new Thread(() -> {
                log.info("      , " + placeOrder);
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                this.completeOrder = placeOrder;
                log.info("        ," + placeOrder);
            }).start();
    
        }
    
        public String getCompleteOrder() {
            return completeOrder;
        }
    
        public void setCompleteOrder(String completeOrder) {
            this.completeOrder = completeOrder;
        }
    }
    
  • Deferred ResultHolder 대상
    @Component
    @Getter
    @Setter
    public class DeferredResultHolder {
        private Map> map = new HashMap>();
    }
    
  • 감청 메시지 큐
    @Slf4j
    @Component
    public class QueueListener implements ApplicationListener {
    
        @Autowired
        private MockQueue mockQueue;
    
        @Autowired
        private DeferredResultHolder deferredResultHolder;
    
        /**
         *   Spring  
         * @param contextRefreshedEvent
         */
        @Override
        public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
            new Thread(()->{
                while (true) {
                    if (StringUtils.isNotBlank(mockQueue.getCompleteOrder())) {
                        String orderNumber = mockQueue.getCompleteOrder();
                        log.info("        :"+orderNumber);
                        deferredResultHolder.getMap().get(orderNumber).setResult("place order success");
                        mockQueue.setCompleteOrder(null);
                    }else{
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    }
    
  • 테스트 결 과 는 다음 과 같다.

  • 보충 하 다
    WebMvcConfigurerAdapter 클래스 를 계승 한 설정 클래스 에 비동기 차단 기 를 등록 할 수 있 습 니 다.다음 과 같 습 니 다.

    좋은 웹페이지 즐겨찾기