Spring MVC 의 비동기 모드(고성능 의 관건)
비동기 모드 가 무엇 인지 알 고 싶 으 면 동기 모드 가 무엇 인지 먼저 알 고 가장 전형 적 인 동기 모드 를 먼저 봐 야 한다.
브 라 우 저 에서 요청 을 합 니 다.웹 서버 에서 스 레 드 처 리 를 하고 처리 결 과 를 브 라 우 저 로 되 돌려 줍 니 다.더 이상 할 말 이 없 는 것 같 습 니 다.대부분의 웹 서버 는 이렇게 처리 합 니 다.지금 생각해 보면 처리 과정 에서 백 엔 드 의 비 즈 니스 논리 서버 를 호출 해 야 한다 면 어떻게 될 까?
조정 하 세 요.위의 그림 에서 보 듯 이 요청 처리 스 레 드 는 Call 이 끝 난 후에 Return 을 기다 리 고 자신 이 차단 상태 에 있 습 니 다.이것 도 절대 다수의 웹 서버 의 방법 이다.일반적으로 이렇게 해도 충분 하 다.왜?첫째,'장시간 처리 서비스'호출 이 많 지 않 고,둘째,요청 수도 많 지 않다.그렇지 않 으 면 이런 모델 에 무슨 문제 가 생 길 까?문제 가 될 수 있 는 것 은 스 레 드 의 부족 을 처리 해 달라 고 요청 하 는 것 입 니 다!요청 처리 스 레 드 의 총 수 는 제한 되 어 있 기 때문에 유사 한 요청 이 많 으 면 모든 처리 스 레 드 가 막 힌 상태 에 있 으 면 새로운 요청 도 처리 할 수 없습니다.즉,서버 의 삼투 능력 에 영향 을 주 는 것 입 니 다.서버 의 모든 성능 을 더욱 잘 발휘 하려 면 이 보 를 사용 해 야 한 다 는 것 도 제목 에서 말 하 는'고성능 의 관건'이다.다음은 비동기 가 어떻게 된 일 인지 살 펴 보 자.
가장 큰 차이 점 은 스 레 드 처리 요청 이 배경 처리 에 대한 호출 에'invoke'방식 을 사용 한 것 입 니 다.즉,바 꾼 후에 바로 돌아 가 고 기다 리 지 않 으 면 스 레 드 처리 요청 이'자유'입 니 다.이 어 다른 요청 을 처리 할 수 있 습 니 다.백 엔 드 처리 가 완료 되면 리 셋 처리 스 레 드 를 연결 하여 호출 결 과 를 처리 할 수 있 습 니 다.이 리 셋 처리 스 레 드 와 요청 처리 스 레 드 는 스 레 드 탱크 의 특정한 스 레 드 일 수 있 습 니 다.서로 관계 가 없 을 수 있 습 니 다.이 리 셋 처리 스 레 드 에서 브 라 우 저 로 내용 을 되 돌려 줍 니 다.이것 이 바로 비동기 적 인 과정 이다.
가 져 온 개선 은 분명 하 다.요청 처리 스 레 드 는 막 을 필요 가 없다.그 능력 은 더욱 충분 하 게 사용 되 어 서버 의 삼투 능력 을 향상 시 켰 다.
Spring MVC 의 사용―Deffered Result
Spring MVC 의 비동기 기능 을 사용 하려 면 먼저 Servlet 3.0 이상 의 버 전 을 사용 하 는 지 확인 해 야 합 니 다.Maven 에서 이렇게 설정 합 니 다.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
제 가 사용 하 는 Servlet 버 전 은 3.1.0 이 고 Spring MVC 버 전 은 4.2.3 이 므 로 최신 버 전 을 사용 하 는 것 을 권장 합 니 다.Spring MVC 의 양호 한 패 키 징 으로 인해 비동기 기능 은 사용 하기에 매우 간단 하 다.전통 적 인 동기 화 모드 의 Controller 는 Model AndView 로 돌아 가 고 비동기 모드 는 Deferred Result
이 예 를 보면:
@RequestMapping(value="/asynctask", method = RequestMethod.GET)
public DeferredResult<ModelAndView> asyncTask(){
DeferredResult<ModelAndView> deferredResult = new DeferredResult<ModelAndView>();
System.out.println("/asynctask !thread id is : " + Thread.currentThread().getId());
longTimeAsyncCallService.makeRemoteCallAndUnknownWhenFinish(new LongTermTaskCallback() {
@Override
public void callback(Object result) {
System.out.println(" , thread id is : " + Thread.currentThread().getId());
ModelAndView mav = new ModelAndView("remotecalltask");
mav.addObject("result", result);
deferredResult.setResult(mav);
}
});
}
longtimeAsyncCallService 는 제 가 장시간 비동기 호출 을 모 의 하 는 서비스 클래스 입 니 다.호출 하면 바로 돌아 갑 니 다.처리 가 끝 났 을 때 스 레 드 를 연결 하여 우리 가 제공 하 는 리 셋 함 수 를 호출 합 니 다.이것 은'그림 3'설명 과 같이 코드 는 다음 과 같 습 니 다.
public interface LongTermTaskCallback {
void callback(Object result);
}
public class LongTimeAsyncCallService {
private final int CorePoolSize = 4;
private final int NeedSeconds = 3;
private Random random = new Random();
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(CorePoolSize);
public void makeRemoteCallAndUnknownWhenFinish(LongTermTaskCallback callback){
System.out.println(" : " + NeedSeconds + " ");
scheduler.schedule(new Runnable() {
@Override
public void run() {
callback.callback(" .");
}
}, " :)", TimeUnit.SECONDS);
}
}
출력 결 과 는:/synctask 호출!thread id is : 46
이 퀘 스 트 완성 시:3 초
비동기 호출 실행 완료,thread id is:47
결 과 를 되 돌려 주 는 스 레 드 와 요청 처리 스 레 드 가 같은 스 레 드 가 아 님 을 알 수 있 습 니 다.
WebAsyncTask 라 는 것 도 있어 요.
Deffered Result
@RequestMapping(value="/longtimetask", method = RequestMethod.GET)
public WebAsyncTask longTimeTask(){
System.out.println("/longtimetask thread id is : " + Thread.currentThread().getId());
Callable<ModelAndView> callable = new Callable<ModelAndView>() {
public ModelAndView call() throws Exception {
Thread.sleep(3000); //
ModelAndView mav = new ModelAndView("longtimetask");
mav.addObject("result", " ");
System.out.println(" thread id is : " + Thread.currentThread().getId());
return mav;
}
};
return new WebAsyncTask(callable);
}
그 핵심 은 Callable/longtimetask 호출 thread id is:56
실행 성공 thread id is:57
이 를 통 해 알 수 있 듯 이 서로 다른 스 레 드 에서 실 행 된 것 입 니 다.그러나 이 WebAsyncTask 는'그림 3'이 설명 한 기술 규격 에 부합 되 지 않 습 니 다.스 레 드 처 리 를 요청 하 는 임 무 를 다른 작업 스 레 드 에 간단하게 전달 하 는 것 일 뿐 입 니 다.
처리 시간 초과
만약 에'장시간 처리 임무'가 계속 돌아 오지 않 았 다 면 우 리 는 클 라 이언 트 를 무한 정 기다 리 게 해 서 는 안 된다.어쨌든'시간 초과'를 해 야 한다.그림:
사실'시간 초과 처리 스 레 드'와'리 셋 처리 스 레 드'는 모두 스 레 드 탱크 의 특정한 스 레 드 일 수 있 습 니 다.저 는 선명 하 게 구분 하기 위해 서 그 렸 을 뿐 입 니 다.이 시간 초과 처 리 를 추가 하 는 것 은 Spring MVC 에서 매우 간단 합 니 다.먼저 WebAsyncTask 코드 를 가지 고 변경 하 십시오.
@RequestMapping(value="/longtimetask", method = RequestMethod.GET)
public WebAsyncTask longTimeTask(){
System.out.println("/longtimetask thread id is : " + Thread.currentThread().getId());
Callable<ModelAndView> callable = new Callable<ModelAndView>() {
public ModelAndView call() throws Exception {
Thread.sleep(3000); //
ModelAndView mav = new ModelAndView("longtimetask");
mav.addObject("result", " ");
System.out.println(" thread id is : " + Thread.currentThread().getId());
return mav;
}
};
WebAsyncTask asyncTask = new WebAsyncTask(2000, callable);
asyncTask.onTimeout(
new Callable<ModelAndView>() {
public ModelAndView call() throws Exception {
ModelAndView mav = new ModelAndView("longtimetask");
mav.addObject("result", " ");
System.out.println(" thread id is :" + Thread.currentThread().getId());
return mav;
}
}
);
return new WebAsyncTask(3000, callable);
}
빨간색 글꼴 부분 코드 를 주의해 서 보 세 요.이것 이 바로 앞에서 언급 한 Callable 이 왜 한 층 을 아웃 소 싱 해 야 하 는 지 입 니 다.WebAsyncTask 에 시간 초과 반전 을 설정 하면 시간 초과 처 리 를 실현 할 수 있 습 니 다.이 예 에서 정상 적 인 처 리 는 3 초 이 고 시간 초과 설정 은 2 초 입 니 다.시간 초과 가 발생 할 수 있 습 니 다.인쇄 log 는 다음 과 같 습 니 다./longtimetask 호출 thread id is:59
실행 시간 초과 thread id is:61
실행 성공 thread id is:80
응?분명히 시간 을 초 과 했 는데 어떻게'집행 성공'을 할 수 있 습 니까?시간 을 초과 하면 시간 을 초과 하고 시간 을 초과 하면 정상 적 인 실행 절 차 를 중단 하지 않 습 니 다.그러나 시간 을 초과 한 후에 우 리 는 클 라 이언 트 에 게'시간 초과'결 과 를 되 돌려 주 었 습 니 다.그 다음 에 정상 적 인 처리 절차 가 성공 하 더 라 도 클 라 이언 트 는 정상 적 인 처리 성공 으로 인해 발생 하 는 결 과 를 받 지 못 합 니 다.이 로 인해 발생 하 는 문 제 는 클 라 이언 트 가'시간 초과'를 보 았 고 실제 작업 이 성공 한 것 입 니까?클 라 이언 트 는 모 르 지만 보통 이것 도 큰 문제 가 아 닙 니 다.사용자 가 브 라 우 저 에서 다시 갱신 하면 되 기 때 문 입 니 다.:D
자,Deffered Result 방식 의 시간 초과 처 리 를 살 펴 보 겠 습 니 다.
@RequestMapping(value = "/asynctask", method = RequestMethod.GET)
public DeferredResult<ModelAndView> asyncTask() {
DeferredResult<ModelAndView> deferredResult = new DeferredResult<ModelAndView>(2000L);
System.out.println("/asynctask !thread id is : " + Thread.currentThread().getId());
longTimeAsyncCallService.makeRemoteCallAndUnknownWhenFinish(new LongTermTaskCallback() {
@Override
public void callback(Object result) {
System.out.println(" , thread id is : " + Thread.currentThread().getId());
ModelAndView mav = new ModelAndView("remotecalltask");
mav.addObject("result", result);
deferredResult.setResult(mav);
}
});
deferredResult.onTimeout(new Runnable() {
@Override
public void run() {
System.out.println(" !thread id is : " + Thread.currentThread().getId());
ModelAndView mav = new ModelAndView("remotecalltask");
mav.addObject("result", " ");
deferredResult.setResult(mav);
}
});
return deferredResult;
}
매우 유사 합 니 다.그 렇 죠?저 는 시간 초 과 를 2 초 로 설정 하고 정상 적 인 처 리 는 3 초 걸 립 니 다.반드시 시간 초 과 를 할 것 입 니 다.실행 결 과 는 다음 과 같 습 니 다./synctask 호출!thread id is : 48
이 퀘 스 트 완성 시:3 초
비동기 호출 실행 시간 초과!thread id is : 51
비동기 호출 실행 완료,thread id is:49
완전히 우리 가 예 상 했 던 것 이다.
예외 처리
별 차이 가 없 는 것 같 습 니 다.Controller 에서 의 처 리 는 이전 동기 화 모드 의 처리 와 같 습 니 다.
@ExceptionHandler(Exception.class)
public ModelAndView handleAllException(Exception ex) {
ModelAndView model = new ModelAndView("error");
model.addObject("result", ex.getMessage());
return model;
}
또 전체적인 이상 처 리 를 해 야 한다.과거의 방법 과 마찬가지 로 여기 서 는 표현 하지 않 는 다.이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
springmvc application/octet-stream problemmistake: Source code: Solution: Summarize: application/octet-stream is the original binary stream method. If the convers...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.