Zabudovaný server Jetty v prostredí Java

1. Prehľad

V tomto článku sa pozrieme na Mólo knižnica. Jetty poskytuje webový server, ktorý môže bežať ako vložený kontajner a ľahko sa integruje do javax.servlet knižnica.

2. Maven závislosti

Na začiatok pridáme závislosti Maven do knižníc jetty-server a jetty-servlet:

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

3. Spustenie servera Jetty so servletom

Spustenie zabudovaného kontajnera Jetty je jednoduché. Musíme vytvoriť nový Server objekt a nastaví jeho spustenie na danom porte:

verejná trieda JettyServer {súkromný serverový server; public void start () hodí výnimku {server = nový Server (); Konektor ServerConnector = nový ServerConnector (server); connector.setPort (8090); server.setConnectors (nový konektor [] {konektor}); }

Povedzme, že chceme vytvoriť koncový bod, ktorý odpovie stavovým kódom HTTP 200, ak všetko dobre dopadne, a jednoduchým užitočným zaťažením JSON.

Vytvoríme triedu, ktorá rozširuje HttpServlet triedy na vybavenie takejto žiadosti; táto trieda bude s jedným vláknom a blokovaná až do dokončenia:

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 \ "}"); }}

Ďalej musíme zaregistrovať BlockingServlet trieda v ServletHandler objekt pomocou addServletWithMapping () a spustite server:

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

Ak chceme otestovať našu servletovú logiku, musíme server spustiť pomocou predtým vytvorenej JettyServer trieda, ktorá je obalom aktuálnej inštancie servera Jetty v rámci testovacieho nastavenia:

@ Pred nastavením public void () vyvolá výnimku {jettyServer = nový JettyServer (); jettyServer.start (); }

Po spustení pošleme testovaciu požiadavku HTTP na server /postavenie koncový bod:

Reťazec url = "// localhost: 8090 / status"; HttpClient client = HttpClientBuilder.create (). Build (); HttpGet request = nový HttpGet (url); HttpResponse response = client.execute (požiadavka); assertThat (response.getStatusLine (). getStatusCode ()). isEqualTo (200);

4. Neblokujúce servlety

Mólo má dobrú podporu pre asynchrónne spracovanie požiadaviek.

Povedzme, že máme obrovský zdroj, ktorý je I / O intenzívny a jeho načítanie blokujúce vykonávajúce vlákno trvá pomerne dlho a trvá dlho. Je lepšie, ak sa toto vlákno bude môcť medzičasom uvoľniť na spracovanie ďalších požiadaviek, namiesto čakania na nejaký vstupno-výstupný zdroj.

Na zaistenie takejto logiky s Jetty môžeme vytvoriť servlet, ktorý bude používať AsyncContext triedy zavolaním na startAsync () metóda na HttpServletRequest. Tento kód nebude blokovať vykonávajúce vlákno, ale vykoná I / O operáciu v samostatnom vlákne a vráti výsledok, keď bude pripravený na použitie AsyncContext.complete () metóda:

verejná trieda AsyncServlet rozširuje HttpServlet {private static String HEAVY_RESOURCE = "Toto je nejaký ťažký zdroj, ktorý bude obsluhovaný asynchronným spôsobom"; protected void doGet (požiadavka HttpServletRequest, odpoveď HttpServletResponse) hodí ServletException, IOException {ByteBuffer content = ByteBuffer.wrap (HEAVY_RESOURCE.getBytes (StandardCharsets.UTF_8)); AsyncContext async = request.startAsync (); ServletOutputStream out = response.getOutputStream (); out.setWriteListener (nový WriteListener () {@Override public void onWritePossible () vyvolá 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 ();}}) ; }}

Píšeme ByteBuffer do OutputStream, a akonáhle je napísaný celý buffer, signalizujeme, že výsledok je pripravený na návrat ku klientovi vyvolaním kompletný () metóda.

Ďalej musíme pridať AsyncServlet ako mapovanie servletu Jetty:

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

Teraz môžeme poslať požiadavku na / heavy / async endpoint - túto požiadavku vybaví mólo asynchrónnym spôsobom:

Reťazec url = "// localhost: 8090 / heavy / async"; HttpClient client = HttpClientBuilder.create (). Build (); HttpGet request = nový HttpGet (url); HttpResponse response = client.execute (požiadavka); assertThat (response.getStatusLine (). getStatusCode ()) .isEqualTo (200); Reťazec responseContent = IOUtils.toString (r esponse.getEntity (). GetContent (), StandardCharsets.UTF_8); assertThat (responseContent) .isEqualTo ("Toto je nejaký ťažký zdroj, ktorý bude obsluhovaný asynchrónnym spôsobom");

Keď naša aplikácia spracováva požiadavky asynchrónnym spôsobom, mali by sme explicitne nakonfigurovať fond vlákien. V ďalšej časti budeme konfigurovať Mólo použiť vlastný fond vlákien.

5. Konfigurácia móla

Keď spustíme našu webovú aplikáciu vo výrobe, budeme chcieť vyladiť, ako server Jetty spracováva požiadavky. To sa deje definovaním fondu vlákien a jeho aplikáciou na náš server Jetty.

K tomu máme tri konfiguračné nastavenia, ktoré môžeme nastaviť:

  • maxThreads - Ak chcete určiť maximálny počet vlákien, ktoré môže Jetty vytvoriť a použiť v bazéne
  • minThreads - Na nastavenie počiatočného počtu vlákien v bazéne, ktoré bude Jetty používať
  • idleTimeout - Táto hodnota v milisekundách určuje, ako dlho môže byť vlákno nečinné, kým sa zastaví a odstráni z fondu vlákien. Počet zostávajúcich vlákien v skupine nikdy neklesne pod minVlákna nastavenie

Pomocou nich môžeme nakonfigurovať zabudované Mólo server programovo odovzdaním nakonfigurovaného fondu vlákien serveru Server konštruktér:

int maxThreads = 100; int minThreads = 10; int idleTimeout = 120; QueuedThreadPool threadPool = nový QueuedThreadPool (maxThreads, minThreads, idleTimeout); server = nový server (threadPool);

Keď potom spustíme náš server, bude používať vlákna z konkrétnej oblasti vlákien.

6. Záver

V tomto rýchlom výučbe sme videli, ako integrovať zabudované servery s Jetty, a otestovali sme našu webovú aplikáciu.

Ako vždy, kód je k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found