자바에 내장 된 Jetty 서버

1. 개요

이 기사에서는 Jetty 라이브러리를 살펴볼 것 입니다. Jetty는 임베디드 컨테이너로 실행할 수있는 웹 서버를 제공하며 javax.servlet 라이브러리 와 쉽게 통합 됩니다.

2. Maven 종속성

시작하기 위해 Jetty-server 및 jetty-servlet 라이브러리에 Maven 종속성을 추가합니다.

 org.eclipse.jetty jetty-server 9.4.3.v20170317   org.eclipse.jetty jetty-servlet 9.4.3.v20170317 

3. 서블릿으로 Jetty 서버 시작

Jetty 내장 컨테이너를 시작하는 것은 간단합니다. 새 서버 개체 를 인스턴스화 하고 지정된 포트에서 시작하도록 설정해야합니다.

public class JettyServer { private Server server; public void start() throws Exception { server = new Server(); ServerConnector connector = new ServerConnector(server); connector.setPort(8090); server.setConnectors(new Connector[] {connector}); }

모든 것이 순조롭게 진행되고 간단한 JSON 페이로드가있는 경우 HTTP 상태 코드 200으로 응답 할 엔드 포인트를 생성한다고 가정 해 보겠습니다.

이러한 요청을 처리하기 위해 HttpServlet 클래스를 확장하는 클래스를 만들 것입니다 . 이 클래스는 단일 스레드이며 완료 될 때까지 차단됩니다.

public class BlockingServlet extends HttpServlet { protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("{ \"status\": \"ok\"}"); } }

다음으로 addServletWithMapping () 메서드 를 사용하여 ServletHandler 객체에 BlockingServlet 클래스 를 등록 하고 서버를 시작해야합니다.

servletHandler.addServletWithMapping(BlockingServlet.class, "/status"); server.start();

Servlet 로직을 테스트 하려면 테스트 설정 내에서 실제 Jetty 서버 인스턴스의 래퍼 인 이전에 만든 JettyServer 클래스를 사용하여 서버를 시작해야합니다 .

@Before public void setup() throws Exception { jettyServer = new JettyServer(); jettyServer.start(); }

시작되면 / status 엔드 포인트에 테스트 HTTP 요청을 보냅니다 .

String url = "//localhost:8090/status"; HttpClient client = HttpClientBuilder.create().build(); HttpGet request = new HttpGet(url); HttpResponse response = client.execute(request); assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);

4. 비 블로킹 서블릿

Jetty는 비동기 요청 처리를 잘 지원합니다.

상당한 시간 동안 실행중인 스레드를로드 차단하는 데 오랜 시간이 걸리는 I / O 집약적 인 리소스가 엄청나게 많다고 가정 해 보겠습니다. I / O 리소스를 기다리는 대신 해당 스레드가 다른 요청을 처리하도록 해방 될 수 있다면 더 좋습니다.

부두와 같은 논리를 제공하기 위해, 우리는 사용하는 서블릿 만들 수 있습니다 AsyncContext의 호출에 의해 클래스를 startAsync () 온 방법 HttpServletRequest의합니다. 이 코드는 실행중인 스레드를 차단하지 않지만 AsyncContext.complete () 메서드를 사용할 준비가되면 결과를 반환하는 별도의 스레드에서 I / O 작업을 수행합니다 .

public class AsyncServlet extends HttpServlet { private static String HEAVY_RESOURCE = "This is some heavy resource that will be served in an async way"; protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ByteBuffer content = ByteBuffer.wrap( HEAVY_RESOURCE.getBytes(StandardCharsets.UTF_8)); AsyncContext async = request.startAsync(); ServletOutputStream out = response.getOutputStream(); out.setWriteListener(new WriteListener() { @Override public void onWritePossible() throws IOException { while (out.isReady()) { if (!content.hasRemaining()) { response.setStatus(200); async.complete(); return; } out.write(content.get()); } } @Override public void onError(Throwable t) { getServletContext().log("Async Error", t); async.complete(); } }); } }

ByteBufferOutputStream에 쓰고 있고 , 전체 버퍼가 쓰여지면 complete () 메서드를 호출하여 결과가 클라이언트에 반환 될 준비가되었음을 알립니다 .

다음으로 AsyncServlet 을 Jetty 서블릿 매핑으로 추가해야합니다 .

servletHandler.addServletWithMapping( AsyncServlet.class, "/heavy/async");

이제 / heavy / async 엔드 포인트에 요청을 보낼 수 있습니다. 이 요청은 Jetty에서 비동기 방식으로 처리됩니다.

String url = "//localhost:8090/heavy/async"; HttpClient client = HttpClientBuilder.create().build(); HttpGet request = new HttpGet(url); HttpResponse response = client.execute(request); assertThat(response.getStatusLine().getStatusCode()) .isEqualTo(200); String responseContent = IOUtils.toString(r esponse.getEntity().getContent(), StandardCharsets.UTF_8); assertThat(responseContent).isEqualTo( "This is some heavy resource that will be served in an async way");

응용 프로그램이 비동기 방식으로 요청을 처리 할 때 스레드 풀을 명시 적으로 구성해야합니다. 다음 섹션에서는 사용자 지정 스레드 풀을 사용 하도록 Jetty 를 구성 합니다.

5. Jetty 구성

프로덕션에서 웹 애플리케이션을 실행할 때 Jetty 서버가 요청을 처리하는 방법을 조정해야 할 수 있습니다. 이는 스레드 풀을 정의하고 Jetty 서버에 적용하여 수행됩니다.

이를 위해 설정할 수있는 세 가지 구성 설정이 있습니다.

  • maxThreads – Jetty가 풀에서 만들고 사용할 수있는 최대 스레드 수를 지정합니다.
  • minThreads – Jetty가 사용할 풀의 초기 스레드 수를 설정합니다.
  • idleTimeout –이 값 (밀리 초)은 스레드가 중지되고 스레드 풀에서 제거되기 전에 스레드가 유휴 상태 일 수있는 시간을 정의합니다. 풀에 남아있는 스레드 수는 minThreads 설정 아래로 내려 가지 않습니다.

이를 통해 구성된 스레드 풀을 Server 생성자 에 전달하여 프로그래밍 방식으로 임베디드 Jetty 서버를 구성 할 수 있습니다 .

int maxThreads = 100; int minThreads = 10; int idleTimeout = 120; QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads, minThreads, idleTimeout); server = new Server(threadPool);

그런 다음 서버를 시작할 때 특정 스레드 풀의 스레드를 사용합니다.

6. 결론

이 빠른 자습서에서는 임베디드 서버를 Jetty와 통합하는 방법을 확인하고 웹 애플리케이션을 테스트했습니다.

항상 그렇듯이 코드는 GitHub에서 사용할 수 있습니다.