2017-11-24 33 views
0

Undertow를 사용하여 진정한 비동기 http 서버를 구축하는 방법을 알고 있습니다. 어떤 요청을 이미 처리하고있는 다른 스레드가 있으면 비동기 적으로 응답을 보내는 방법은 무엇입니까?
는이 같은 코드를 썼습니다 : 없음 데이터 및 로그에언더 타운. 다른 스레드와 비동기 응답

Undertow server = Undertow.builder() 
      .addHttpListener(8080, "localhost") 
      .setHandler(exchange -> { 
       CompletableFuture.runAsync(() -> { 
        try { 
         Thread.sleep(100); 
        } catch (InterruptedException e) { 
         throw new RuntimeException(e); 
        } 
       }).thenAccept(string -> { 
        exchange.getResponseHeaders() 
          .put(Headers.CONTENT_TYPE, "text/plain"); 
        exchange.getResponseSender().send("Hello World"); 
        exchange.endExchange(); 
       }).exceptionally(throwable -> { 
        System.out.println(throwable.toString()); 
        return null; 
       }); 
      }).build(); 
    server.start(); 

그러나이 서버 응답 (200)

java.lang.IllegalStateException : UT000127 : 응답이 이미 발송되었습니다

다음과 같이 io.undertow.server.HttpServerExchange # dispatch (java.lang.Runnable) 메소드를 사용할 때 :

Undertow server = Undertow.builder() 
      .addHttpListener(8080, "localhost") 
      .setHandler(exchange -> { 

       exchange.dispatch(() -> { 

        CompletableFuture.runAsync(() -> { 
         try { 
          Thread.sleep(100); 
         } catch (InterruptedException e) { 
          throw new RuntimeException(e); 
         } 
        }).thenAccept(string -> { 
         exchange.getResponseHeaders() 
           .put(Headers.CONTENT_TYPE,"text/plain"); 
         exchange.getResponseSender().send("Hello World"); 
         exchange.endExchange(); 
        }).exceptionally(throwable -> { 
         System.out.println(throwable.toString()); 
         return null; 
        }); 

       }); 
      }).build(); 
    server.start(); 

물론 "Hello World"는 예상대로 응답하지만 서버는 모든 요청에 ​​대해 새 스레드를 만듭니다!

(jvisualvm 후 10 개 병렬 요청) 나 새로운 프로젝트를 생성

jvisualvm after 10 parallel requests

+0

추신을 나는 그것을 주된 방법으로 실행한다. – QIvan

답변

0

역류가이 방법을 지원하지은이를 해결하려면

https://github.com/hank-whu/undertow-async

package io.undertow.async.pingpong; 

import java.io.IOException; 
import java.util.concurrent.CompletableFuture; 

import io.undertow.async.handler.AsyncHttpHandler; 
import io.undertow.async.io.PooledByteBufferInputStream; 
import io.undertow.async.io.PooledByteBufferOutputStream; 
import io.undertow.connector.ByteBufferPool; 
import io.undertow.server.HttpServerExchange; 
import io.undertow.util.StatusCodes; 

public class PingPongAsyncHttpHandler extends AsyncHttpHandler { 

    @Override 
    protected void handleAsyncRequest(HttpServerExchange exchange, PooledByteBufferInputStream content) 
      throws Exception { 

     CompletableFuture// 
       .completedFuture(content)// init 
       .thenApplyAsync(this::readBytesAndClose)// read 
       .thenApplyAsync(bytes -> {// write 
        ByteBufferPool byteBufferPool = exchange.getConnection().getByteBufferPool(); 
        PooledByteBufferOutputStream output = new PooledByteBufferOutputStream(byteBufferPool); 
        write(output, bytes); 
        return output; 
       })// 
       .thenAcceptAsync(output -> send(exchange, StatusCodes.OK, output)); 
    } 

    private byte[] readBytesAndClose(PooledByteBufferInputStream content) { 
     try { 
      byte[] bytes = new byte[content.available()]; 
      content.read(bytes); 
      return bytes; 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } finally { 
      try {// must close it 
       content.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    private void write(PooledByteBufferOutputStream output, byte[] bytes) { 
     try { 
      output.write("asycn response: "); 
      output.write(bytes); 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } 
    } 

}