programing

봄 mvc에서 서블릿 3.1을 사용하는 방법?

minimums 2023. 10. 15. 17:10
반응형

봄 mvc에서 서블릿 3.1을 사용하는 방법?

사용 가능한 두 가지 기능이 있습니다.

  1. servlet 3.0을 사용하면 컨테이너 스레드와 다른 스레드에서 요청을 처리할 수 있습니다.

  2. 서블릿 3.1은 읽기/쓰기 스레드를 차단하지 않고 소켓에 읽기/쓰기 가능

인터넷에는 서블릿 3.0 기능에 대한 많은 예들이 있습니다.봄에 아주 쉽게 사용할 수 있습니다.우리는 그냥 돌아가야 합니다.DefferedResult아니면CompletableFuture

하지만 봄에 서블릿 3.1을 사용한 예를 찾을 수 없습니다.내가 알기로는 우리가 등록해야 하는 것으로 알고 있습니다.WriteListener그리고.ReadListener그리고 실내에서 돔더티 작업을 합니다.하지만 리스너들의 예를 찾을 수가 없습니다.저는 그것이 매우 쉽지 않다고 믿습니다.

청취자 구현에 대한 설명과 함께 봄에 서블릿 3.1 기능의 예를 제시해주시겠습니까?

서블릿 3.1의 경우 Reactive Streams 브리지를 사용하여 무중단 I/O 지원

서블릿 3.1+ 용기

모든 서블릿 3.1+ 컨테이너에 WAR로 배포하려면 WAR에 {api-spring-framework}/web/server/adapter/AbstractReactiveWebInitializer.html[AbstractReactiveWebInitializer]를 확장하여 포함할 수 있습니다.해당 클래스는 HttpHttpHttpHandlerAdapter를 ServletHttpHandlerAdapter로 랩핑하고 Servlet으로 등록합니다.

따라서 비동기 지원을 추가하는 AbstractReactiveWebInitializer를 확장해야 합니다.

registration.setAsyncSupported(true);

ServletHttpHandler 어댑터의 지원

AsyncContext asyncContext = request.startAsync();

Spring/Servlet 3.1 non-blocking HTTP API 선언의 예를 찾는다면 다음을 시도해 보십시오.

@GetMapping(value = "/asyncNonBlockingRequestProcessing")
public CompletableFuture<String> asyncNonBlockingRequestProcessing(){
        ListenableFuture<String> listenableFuture = getRequest.execute(new AsyncCompletionHandler<String>() {
            @Override
            public String onCompleted(Response response) throws Exception {
                logger.debug("Async Non Blocking Request processing completed");
                return "Async Non blocking...";
             }
        });
        return listenableFuture.toCompletableFuture();
}

서블릿 컨테이너 수준(Tomcat 8.5+, Jetty 9.4+, WildFly 10+)에서 Spring Web 5.0+ 및 Servlet 3.1 지원 필요

몇 가지 사례를 추적하는 것은 그리 어렵지 않을 것입니다.WASdev/sample.javaee7.servlet.nonblocking에서 IBM 제품을 찾았습니다.javax.servletSpring 또는 Spring Boot의 API는 Spring에 주입을 요청하는 것입니다.HttpServletRequest아니면HttpServletResponse. 따라서 간단한 예로 다음을 들 수 있습니다.

@SpringBootApplication
@Controller
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @RequestMapping(path = "")
    public void writeStream(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ServletOutputStream output = response.getOutputStream();
        AsyncContext context = request.startAsync();
        output.setWriteListener(new WriteListener() {
            @Override
            public void onWritePossible() throws IOException {
                if ( output.isReady() ) {
                    output.println("WriteListener:onWritePossible() called to send response data on thread : " + Thread.currentThread().getName());
                }
                context.complete();
            }
            @Override
            public void onError(Throwable t) {
                context.complete();
            }
        });
    }
}

이것은 단순히 다음과 같은 것을 만듭니다.WriteListener이를 요청 출력 스트림에 연결한 다음 반환합니다.화려한 것은 없습니다.

에디츠: 요점은 서블릿 컨테이너(예: Tomcat)가 호출한다는 것입니다.onWritePossible데이터를 차단하지 않고 작성할 수 있는 경우서블릿 3.1을 사용한 Non-blocking I/O에서의 자세한 내용: Java EE 7(TOTD #188)을 사용한 확장 가능한 애플리케이션.

수신자(및 작성자)는 내용을 읽을 수 있거나 차단 없이 쓸 수 있는 경우 호출되는 콜백 메서드를 가지고 있습니다.

그러므로onWritePossible다음의 경우에만 호출됩니다.out.println차단 없이 호출할 수 있습니다.

setXXXListener 메서드를 호출하면 기존 I/O 대신 비차단 I/O가 사용됨을 나타냅니다.

아마 당신이 해야 할 일이output.isReady바이트를 계속 쓸 수 있는지 확인합니다.블록 크기에 대해 발신자/수신자와 암묵적으로 합의해야 할 것 같습니다.한 번도 사용해본 적이 없어서 잘 모르겠습니다만, Spring framework에서 이것에 대한 예시를 요청하셨고 그것이 제공됩니다.

따라서 onWritePossible은 out일 때만 호출됩니다.println은 차단 없이 호출할 수 있습니다.맞는 말인 것 같은데, 바이트를 몇 개까지 쓸 수 있는지 어떻게 알 수 있나요?이걸 어떻게 조절해야 할까요?

편집 2: 정확한 답을 드릴 수 없는 매우 좋은 질문입니다.저는 그렇게 생각합니다.onWritePossible서버가 메인 서블릿과 별도의 (asynchron) 스레드에서 코드를 실행할 때 호출됩니다.당신이 확인한 예로부터input.isReady()아니면output.isReady()송신자/수신자가 더 많은 것을 준비할 때까지 스레드가 차단된다고 가정합니다.이 작업은 비동기적으로 수행되므로 서버 자체는 차단되지 않으며 다른 요청을 처리할 수 있습니다.저는 이것을 사용해 본 적이 없어서 전문가가 아닙니다.

내가 블록 크기에 대해 송신자/수신자와 암묵적으로 합의할 것이라고 말했을 때, 만약 수신자가 1024 바이트 블록을 수용할 수 있다면 당신은 그 양을 다음과 같이 쓸 것입니다.output.isReady사실입니다.당신은 문서를 읽음으로써 그것에 대한 지식을 가져야 할 것이고, 그것에 대한 api에는 아무것도 없습니다.그렇지 않으면 단일 바이트를 쓸 수 있지만 oracle의 예제에서는 1024바이트 블록을 사용합니다.1024바이트 블록은 스트리밍 I/O를 위한 상당히 표준적인 블록 크기입니다.위의 예는 a에서 바이트를 쓰기 위해 확장되어야 할 것입니다.while오라클 예제에 표시된 것과 같은 루프입니다.그것은 독자들에게 남은 연습문제입니다.

프로젝트 원자로와 스프링 웹플럭스는 다음과 같은 개념을 가지고 있습니다.backpressure좀 더 신중하게 해결할 수 있을 겁니다 그것는 그 에 대해 .그것은 별개의 질문일 것이고 저는 그 커플이 어떻게 송신자와 수신자를 연결하는지에 대해 자세히 조사하지 않았습니다.

서블릿 3.0 - 컨테이너 스레드와 처리 스레드를 분리합니다.지연된 결과 또는 완료 가능을 반환합니다.미래.따라서 컨트롤러 처리는 서버 요청 처리 스레드와는 다른 스레드에 있을 수 있습니다.서버 스레드 풀은 더 많은 수신 요청을 자유롭게 처리할 수 있습니다.

하지만 여전히 IO는 차단되고 있습니다.입력 및 출력 스트림에 대한 읽기 및 쓰기(느린 클라이언트에 대한 응답 수신 및 전송).

서블릿 3.1 - IO를 포함한 모든 과정을 차단하지 않습니다.Spring에서 Servlet 3.1을 사용한다는 것은 직접적으로 너무 번거로운 ReadListener와 WriteListener 인터페이스를 사용해야 한다는 것을 의미합니다.또한, 동기화 및 차단 기능인 서블릿(Servlet), 필터(Filter)와 같은 서블릿(Servlet) API를 사용하는 것에서 벗어나야 합니다.대신 Resactive Streams API를 사용하고 Servlet 3.1을 지원하는 Spring Webflux를 사용합니다.

언급URL : https://stackoverflow.com/questions/56836013/how-to-use-servlet-3-1-in-spring-mvc

반응형