스프링 3.2 이일민 Epril toby.epril.com 1
2
스프링 3.2 2012년 12월 3.x의마지막업그레이드 주로 Spring@MVC 3
ibatis / mybatis package org.springframework.orm.ibatis.support; @Deprecated public abstract class SqlMapClientDaoSupport extends DaoSupport { 4
Servlet 3 based Asynchronous Request Processing 비동기요청처리 5
비동기요청처리학습순서 비동기요청처리 Servlet 3.0 이전의비동기요청처리 Servlet 3.0의비동기요청처리 스프링 3.2의 @MVC 비동기요청처리 비동기요청처리의미래 6
비동기 (asynchronous) 의미? 둘이상의사물이나사건이동시에존재 [ 발생 ] 하지않는 시스템간의상호작용이어느정도의시차를두고일어나는것. 비동기 = 논블록킹? 그럼동기 = 블록킹? Java NIO = 비동기? 7
비동기 (asynchronous) 요청처리 ( 메소드호출을통한 ) 작업요청이어떻게진행되고어떻게결과를받는가 작업진행이요청을보낸쓰레드에서? 결과가메소드리리턴값인가? A B 8
블록킹, 논블록킹 블록킹 요청한작업을마칠때까지대기 ( 리턴 X) InputStream.read() This method blocks until input data is available, the end of the stream is detected, or an exception is thrown. 논블록킹 요청한작업을즉시마칠수없으면그냥리턴 Selector.selectNow() This method performs a non-blocking selection operation 주로 IO 읽기, 쓰기메소드호출 9
블록킹 IO 와쓰레드 IO 처리를위해쓰레드하나할당 Thread per Connection 대기 T IO 10
논블록킹 IO 와쓰레드 하나의쓰레드가여러개의 IO 처리가능 T IO 11
블록킹메소드 + 논블록킹 IO Selector.select() This method performs a blocking selection operation IO S M IO IO IO 블록킹 논블록킹 12
블록킹, 논블록킹 vs 동기, 비동기 오해 블록킹 = 동기 논블록킹 = 비동기 가능조합 동기블록킹 동기논블록킹 비동기논블록킹 비동기블록킹 (?) 13
동기 (synchronous) 요청처리 작업요청의결과를직접받는것 메소드호출을통한작업요청의결과를리턴값으로받으면동기요청처리 요청 결과 요청처리 14
비동기 (asynchronous) 요청처리 작업요청결과를이후에간접적으로받는것 메소드호출의리턴값이작업결과가아님 별도의쓰레드에서작업수행 요청 결과 요청처리 15
동기 = 블록킹? 동기블록킹 결과가나올때까지기다렸다리턴값으로결과전달 동기논블록킹 결과가없으면바로리턴 결과가있으면리턴값으로결과전달 Selector.selectNow() 16
비동기 = 논블록킹? 비동기논블록킹 작업요청을받아서별도로진행하게하고바로리턴 ( 논블록킹 ) 결과는별도의작업후간접적으로전달 비동기블록킹? 리턴값으로결과를줄것도아닌데왜블록킹? 하지만두가지이상의대상 ( 메소드호출 +IO 처리 ) 에대해동시에설명하면비동기메소드요청처리 + 동기 IO 도얼마든지가능 17
비동기요청처리결과전달 콜백 비동기요청처리시콜백전달 요청처리가완료되면콜백호출 결과조회 Future<V> 요청이완료됐는지확인 18
java.nio.channels.asynchronousbytechannel <A> void read(bytebuffer dst, A attachment, CompletionHandler<Integer,? super A> handler); Future<Integer> read(bytebuffer dst); public interface CompletionHandler<V,A> { void completed(v result, A attachment); void failed(throwable exc, A attachment); } public interface Future<V> { boolean isdone(); V get() throws InterruptedException, ExecutionException; } 19
스프링템플릿 / 콜백도비동기? 대부분동기 - 블록킹 JdbcTemplate.jqueryForObject() 콜백은템플릿내에서동작하는바뀌는로직을전달하기위한용도 20
비동기작업요청의필요성 시간이오래걸리는작업을별도로수행 자원 ( 쓰레드 ) 의효율적인사용 Event-driven / 서버 push (long-polling) 21
SERVLET 3.0 이전의비동기 요청처리 22
웹애플리케이션의비동기작업 시간이오래걸리는작업 결과를바로확인할필요가없는작업 B 요청 S A 결과 S 23
@Async 별도의쓰레드에서비동기작업수행 @Async public void batchjob() { } 24
Future 이용비동기작업결과확인 Future<V>: 비동기작업결과 @Async 메소드의리턴타입을 Future<V> B 요청 S F A 결과 S 25
@Async Future<V> @Async public Future<String> dobatchjob() { // 요청처리 } return new AsyncResult<String>(result); Spring32.asynctask/result 26
SERVLET 3.0 의비동기요청처리 27
서블릿단위의비동기요청처리 @Async/Future는 HTTP요청 / 응답이많아진다 한번의 HTTP요청 / 응답내에서작업 서블릿쓰레드의대기상태를최소화 B 요청 대기 응답 S DB, Remote, Event 28
서블릿단위의비동기요청처리 비동기작업을시작하거나대기상태로만들고서블릿작업즉시종료 가용서블릿쓰레드증가 B 요청 응답 S S DB, Remote, Event 29
비동기요청처리활용 (1) 시간이오래걸리는외부연동작업을비동기로 Executor 에요청 작업 ( 비동기, 애플리케이션 ) 쓰레드에서작업수행 B 요청 S TE WTP 응답 S WT Servlet3async.asyncservlet - thread 30
비동기요청처리활용 (1) 시나리오 서블릿쓰레드최대 100 개 외부연동을포함한장시간수행요청 50 개 동기방식 장시간요청처리중가용쓰레드 50 개 비동기방식 작업쓰레드풀 10 개 가용쓰레드 90 개 DB 나웹 API 호출같은외부연동을논블록킹으로할수있다면가용쓰레드 99 개 async-mysql-connector, adbcj Support an asynchronous API for RestTemplate (Spring 4.0) 31
서블릿 3 비동기요청처리 @WebServlet(urlPatterns="/asynchello", asyncsupported=true) public class AsyncServlet extends HttpServlet { } final AsyncContext ac = req.startasync(); this.executor.execute(new Runnable() { // 비동기작업 // ac.dispatch() 또는 ac.complete() }); Servlet3async.asyncservlet sync/async 32
톰캣 7 과서블릿 3.0 비동기요청처리 톰캣의 HTTP Connector 디폴트 : org.apache.coyote.http11.http11protocol HTTP/1.1 블록킹 IO org.apache.coyote.http11.http11nioprotocol 서블릿비동기요청처리를사용하려면 NIO Connector 설정필요 한계 NIO Connector 를사용하더라도서블릿의 IO 는비동기방식아니므로 HTTP 응답을처리하기위해서서블릿쓰레드가필요 Servlet3async.asyncservlet - nio 33
비동기요청처리활용 (2) 서블릿응답을이벤트발생시까지대기 다른요청, JMS, Redis(pub/sub), 스케줄러, 서버 push - 롱폴링 별도의작업쓰레드생성필요없음 B 요청 S 응답 S Event 34
비동기요청처리활용 (2) 시나리오 서블릿쓰레드최대 100 개 동기방식 롱 - 폴링요청최대 100 개 가용쓰레드 0 다른요청불가능 비동기방식 롱 - 폴링요청최대 10,000 개 ( 톰캣기본설정, OS 지원 ) 가용쓰레드 100 ( 응답보낼때만잠시사용 ) 35
스프링 3.2 의비동기요청처리 36
서블릿 3.0 비동기의단점 Executor/ 쓰레드풀관리코드작성부담 서블릿으로개발! Spring@MVC 컨트롤러사용불가 37
서블릿 3.2 비동기기능 기존스프링 @MVC 컨트롤러작성방식과동일 활용 1( 쓰레드풀을이용한비동기작업 ) 과활용 2( 응답을지연시키고별도이벤트에의해서처리 ) 시나리오에모두 @MVC 컨트롤러코드거의그대로사용 활용 1 Callable, WebAsyncTask 활용 2 DeferredResult 38
비동기 @MVC 컨트롤러 컨트롤러리턴타입을다음중하나로변경 Callable WebAsyncTask DeferredResult @RequestMapping("/hello") public String hello() { @RequestMapping("/hello") public Callable<String> hello() { 39
java.util.concurrent.callable Runnable 과유사하게별도의쓰레드에서실행되는코드 실행결과타입지정 public interface Callable<V> { V call() throws Exception; } 40
Callable 컨트롤러 @MVC 컨트롤러의모든리턴타입사용 뷰이름, ModelAndView, @ResponseBody @RequestMapping("/call") @ResponseBody public Callable<String> call() { return new Callable<String>() { @Override public String call() throws Exception { // 작업 String res =... } return result; }}; 41
Callable 코드실행 스프링이제공하는 AsyncTaskExecutor 로실행 디폴트는 SimpleAsyncTaskExecutor 적절한 AsyncTaskExecutor 설정필요 @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { public void configureasyncsupport(asyncsupportconfigurer configurer) { ThreadPoolTaskExecutor e = new ThreadPoolTaskExecutor(); e.setcorepoolsize(5); e.initialize(); configurer.settaskexecutor(e); } 42
WebAsyncTask Callable 과동일한방식 Callable 실행쓰레드풀지정 작업종류에따라쓰레드풀분리 Facebook API 쓰레드풀, DB 쓰레드풀, AsyncTaskExecutor 빈이름사용 Timeout 설정 Callable 을 WebAsyncTask 에담아서리턴 43
WebAsyncTask @RequestMapping("/facebooklink") public WebAsyncTask<String> facebooklink() { return new WebAsyncTask<String>( 30000L, // Timeout "facebooktaskexecutor", // TaskExecutor new Callable<String>() { @Override public String call() throws Exception { // 작업 return result; } } ); } 44
DeferredResult MVC 컨트롤러리턴값을별개의작업에서지정할수있도록해줌 JMS, AMQP, 스케줄러, Email, IM, Redis, 다른 HTTP 요청 작업쓰레드를생성하지않는다 빈의필드에정의된 Queue 등에저장해두고이벤트발생시사용하고제거 45
DeferredResult 컨트롤러 Callable 과마찬가지로 @MVC 컨트롤러메소드의리턴값타입지정 @RequestMapping("/async") @ResponseBody public DeferredResult<String> async() { final DeferredResult<String> result = new DeferredResult<>(); queue.add(result); } return result; 46
DeferredResult 결과지정 Queue 등에저장된 DeferredResult 를가져와 @RequestMapping 메소드리턴값지정 @RequestMapping("/event") @ResponseBody public String event(string msg) { for(deferredresult<string> result : queue) { result.setresult(msg); } } return "OK"; 47
DEMO 48
49
Timeout 설정 톰캣서버 Connector asynctimeout 디폴트 10 초 <Connector connectiontimeout="20000" asynctimeout= 60000" protocol="org.apache.coyote.http11.http11nioprotocol" AsyncSupportConfigurer public void configureasyncsupport(asyncsupportconfigurer configurer) { configurer.setdefaulttimeout(30000); WebAsyncTask, DeferredResult 50
Timeout 처리 DeferredResult.onTimeout final DeferredResult<String> result = new DeferredResult<>(); final Date start = new Date(); result.ontimeout(new Runnable() { @Override public void run() { // Timeout 처리 } }); Timeout Result final DeferredResult<String> result = new DeferredResult<>(60000L, "TIMEOUT"); 51
Timeout 인터셉터 public interface CallableProcessingInterceptor { <T> Object handletimeout(nativewebrequest request, Callable<T> task) throws Exception; 52
비동기 @MVC 고려할것 예외처리 HandlerExceptionResolver 방식 Callable: throw Ex() DeferredResult: seterrorresult(error value 또는 ex) 비동기지원필터 비동기지원인터셉터 ThreadLocal 사용 서블릿요청 / 응답에하나이상의쓰레드사용 53
스프링설정 54
비동기 @MVC 를위한 web.xml <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>spring</servlet-name> <servletclass>org.springframework.web.servlet.dispatcherservlet </servlet-class> <init-param>...</init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> 55
비동기 @MVC 를위한스프링 XML <mvc:annotation-driven> <mvc:async-support default-timeout="3000" task-executor="asynctaskexecutor"> <mvc:callable-interceptors> <bean class="async.timeoutprocessinginterceptor" /> </mvc:callable-interceptors> </mvc:async-support> </mvc:annotation-driven> 56
web.xml 제거 서블릿 3.0 ServletContainerInitializer 스프링 3.1 WebApplicationInitializer 스프링 3.2 AbstractAnnotationConfigDispatcherServletInitializ er 57
루트애플리케이션컨텍스트 - XML <listener> <listener-class> org.springframework.web.context.contextloaderlistener </listener-class> </listener> <context-param> <param-name>contextclass</param-name> <param-value> org.springframework.web.context.support.annotationconfigwebapplic ationcontext </param-value> </context-param> <context-param> <param-name>contextconfiglocation</param-name> <param-value>myproject.config.appconfig</param-value> </context-param> 58
루트애플리케이션컨텍스트 S3.1 AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext(); ac.register(appconfig.class); ServletContextListener listener = new ContextLoaderListener(ac); servletcontext.addlistener(listener); 59
루트애플리케이션컨텍스트 S3.2 protected Class<?>[] getrootconfigclasses() { return new Class<?>[] { AppConfig.class }; } 60
서블릿애플리케이션컨텍스트 - XML <servlet> <servlet-name>spring</servlet-name> <servletclass>org.springframework.web.servlet.dispatcherservlet</servlet- class> <init-param> <param-name>contextclass</param-name> <param-value> org.springframework.web.context.support.annotationconfigwebapplic ationcontext </param-value> </init-param> <init-param> <param-name>contextconfiglocation</param-name> <param-valuemyproject.config.appconfig</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> 61
서블릿애플리케이션컨텍스트 S3.1 AnnotationConfigWebApplicationContext sac = new AnnotationConfigWebApplicationContext(); sac.register(webconfig.class); ServletRegistration.Dynamic dispatcher = servletcontext.addservlet( "spring", new DispatcherServlet(sac)); dispatcher.setloadonstartup(1); dispatcher.addmapping("/"); 62
서블릿애플리케이션컨텍스트 S3.2 protected Class<?>[] getservletconfigclasses() { return new Class<?>[] { WebConfig.class }; } protected String[] getservletmappings() { return new String[] { "/" }; } 63
기타기능 64
ContentNegotiationManager 요청정보의미디어타입을결정하는전략관리 기존 ContentNegotiatingViewResolver, @RequestMapping 의 consumes, produces 등에서다루던내용을일관된방식으로정리 RequestMappingHandlerMapping, RequestMappingHandlerAdapter, ExceptionHandlerExceptionResolver, ContentNegotiatingViewResolver 등에적용 65
Matrix Variables http://www.w3.org/designissues/matrixuris.h tml 팀버너스리제안 다양한용도로사용중 Servlet jsessionid http://www.myserver.com/index.html;jsessionid=1234 JAX-RS: @MatrixParam @MatrixVaraible 66
GenericHttpMessageConverter Generic 타입파라미터지원 Jaxb2CollectionHttpMessageConverter MappingJackson2HttpMessageConverter MappingJacksonHttpMessageConverter RestTemplate ParameterizedTypeReference @RequestBody 67
@ControllerAdvice 컨트롤러에적용되는어드바이스정의 @ExceptionHandler @InitBinder @ModelAttribute 빈스캔대상 @Component 메타애노테이션 68
참고정보 스프링 3.2 레퍼런스 / API Doc What s New in Spring 3.2 http://www.youtube.com/watch?v=gsswmlikf-m Serlvet 3.0 스펙 / 서적 스프링 3.2 실무프로젝트 ( 예정 ) 69
감사합니다 70