de Martin Budi

O introducere în Vert.x, cel mai rapid framework Java de astăzi

O introducere in Vertx cel mai rapid framework Java de

Dacă ați cercetat recent „cel mai bun cadru web”, s-ar putea să fi dat peste benchmark-urile Techempower unde sunt clasificate peste trei sute de cadre. Acolo s-ar putea să fi observat că Vert.x este unul dintre primele clasate, dacă nu chiar primul prin unele măsuri.

Deci, să vorbim despre asta.

Vert.x este un cadru web poliglot care împărtășește funcționalități comune între limbile suportate Java, Kotlin, Scala, Ruby și Javascript. Indiferent de limbă, Vert.x funcționează pe mașina virtuală Java (JVM). Fiind modulară și ușoară, este orientată spre dezvoltarea microserviciilor.

Punctele de referință Techempower măsoară performanța actualizării, preluării și livrării datelor dintr-o bază de date. Cu cât sunt solicitate mai multe cereri pe secundă, cu atât mai bine. Într-un astfel de scenariu IO în care este implicată puțină informatică, orice cadru non-blocant ar avea un avantaj. În ultimii ani, o astfel de paradigmă este aproape inseparabilă de Node.js, care a popularizat-o cu bucla sa de evenimente cu un singur fir.

Vert.x, la fel ca Node, operează o singură buclă de eveniment. Dar Vert.x profită și de JVM. În timp ce nodul rulează pe un singur nucleu, Vert.x menține un pool de fire cu o dimensiune care se poate potrivi cu numărul de nuclee disponibile. Cu suport mai mare de concurență, Vert.x este potrivit nu numai pentru procesele IO, ci și pentru procesele cu procesor greu, care necesită calcul paralel.

Totuși, buclele evenimentului reprezintă jumătate din poveste. Cealaltă jumătate are puțin de-a face cu Vert.x.

Pentru a vă conecta la o bază de date, un client necesită un driver de conector. În domeniul Java, cel mai comun driver pentru Sql este JDBC. Problema este că acest driver se blochează. Și se blochează la nivelul soclului. Un fir va rămâne întotdeauna blocat acolo până când se întoarce cu un răspuns.

Inutil să spun că șoferul a fost un obstacol în realizarea unei aplicații complet non-blocante. Din fericire s-au înregistrat progrese (deși neoficiale) în ceea ce privește un șofer asincron cu mai multe furci active, printre care:

Regula de aur

Vert.x este destul de simplu de utilizat, iar un server http poate fi creat cu câteva linii de cod.

Metoda requestHandler este locul în care bucla evenimentului furnizează evenimentul cererii. Deoarece Vert.x nu are opinii, gestionarea acestuia este un stil gratuit. Dar rețineți singura regulă importantă a firului de non-blocare: nu-l blocați.

Când lucrăm cu concurență, putem extrage din atâtea opțiuni disponibile astăzi, cum ar fi Promise, Future, Rx, precum și modul idiomatic propriu al Vert.x. Dar pe măsură ce complexitatea unei aplicații crește, nu are suficientă funcționalitatea asincronă. De asemenea, avem nevoie de ușurința coordonării și înlănțuirii apelurilor, evitând în același timp infernul de apel invers, precum și transmiterea oricărei erori cu grație.

Scala Future îndeplinește toate condițiile de mai sus cu avantajul suplimentar de a fi bazat pe principii de programare funcționale. Deși acest articol nu explorează Scala Future în profunzime, îl putem încerca cu o aplicație simplă. Să presupunem că aplicația este un serviciu API pentru a găsi un utilizator dat de id-ul său:

Există trei operații implicate: verificarea parametrului cererii, verificarea dacă ID-ul este valid și preluarea datelor. Vom înfășura fiecare dintre aceste operații într-un viitor și vom coordona execuția într-o structură „pentru înțelegere”.

  • Primul pas este de a potrivi cererea cu un serviciu. Scala are o caracteristică puternică de potrivire a modelelor pe care o putem folosi în acest scop. Aici interceptăm orice mențiune despre „/ user” și o transmitem în serviciul nostru.
  • Următorul este nucleul acestui serviciu în care viitorul nostru este aranjat într-o secvență de înțelegere. Primul viitor f1 înfășoară verificarea parametrilor. Vrem în mod specific să preluăm id-ul din cererea get și să-l aruncăm în int. (Scala nu necesită returnare explicită dacă valoarea returnată este ultima linie a metodei.) După cum vedeți, această operațiune ar putea arunca o excepție, deoarece ID-ul ar putea să nu fie un int sau chiar să nu fie disponibil, dar acest lucru este în regulă pentru moment .
  • Al doilea viitor f2 verifică validitatea id-ului. Blochăm orice ID mai mic de 100 apelând explicit Future.failed cu propria noastră CustomException. În caz contrar, trecem un viitor gol sub forma Future.unit ca validare reușită.
  • Ultimul viitor f3 recuperează utilizatorul cu ID-ul furnizat de f1. Deoarece acesta este doar un eșantion, nu ne conectăm cu adevărat la o bază de date. Întoarcem doar niște șiret simulat
  • Hartă execută aranjamentul care furnizează datele utilizatorului de la f3 apoi îl imprimă în răspuns.
  • Acum, dacă în orice parte a secvenței apare o eroare, un Throwable este trecut la recupera. Aici îi putem asocia tipul cu o strategie de recuperare adecvată. Privind înapoi în codul nostru, am anticipat mai multe eșecuri potențiale, cum ar fi ID-ul lipsă sau ID-ul care nu era int sau nu valabil, ceea ce ar genera excepții specifice. Le gestionăm pe fiecare dintre acestea în handleException, transmitând un mesaj de eroare clientului.

Acest aranjament oferă nu numai un flux asincron de la început până la sfârșit, ci și o abordare curată a gestionării erorilor. Și, întrucât este simplificat în toate gestionarele, ne putem concentra asupra lucrurilor importante, cum ar fi interogarea bazei de date.

Verticule, autobuz de evenimente și altele

Vert.x oferă, de asemenea, un model de concurență numit verticul, care seamănă cu sistemul Actor. (Dacă doriți să aflați mai multe, mergeți la Ghidul actorului Akka.) Verticle își izolează starea și comportamentul pentru a oferi un mediu sigur pentru fire. Singura modalitate de a comunica cu acesta este printr-un autobuz de evenimente.

Cu toate acestea, magistrala de evenimente Vert.x necesită ca mesajele sale să fie String sau JSON. Acest lucru face dificilă trecerea obiectelor arbitrare non-POJO. Și într-un sistem de înaltă performanță, tratarea conversiei JSON este nedorită, deoarece impune un anumit cost de calcul. Dacă dezvoltați aplicații IO, este mai bine să nu utilizați nici verticală, nici autobuz de evenimente, deoarece astfel de aplicații au puțină nevoie de stat local.

Lucrul cu unele componente Vert.x poate fi, de asemenea, destul de dificil. S-ar putea să găsiți lipsa documentației, comportamentul neașteptat și chiar eșecul de a funcționa. Vert.x ar putea suferi de propria ambiție, deoarece dezvoltarea de noi componente ar necesita portarea în multe limbi. Aceasta este o întreprindere dificilă. Din acest motiv, a rămâne la bază ar fi cel mai bun.

Dacă dezvoltați un API public, atunci vertx-core ar trebui să fie suficient. Dacă este o aplicație web, puteți adăuga vertx-web care oferă gestionarea parametrilor http și autentificarea JWT / Session. Aceștia doi sunt cei care oricum au dominat reperele. Există unele scăderi ale performanței în unele teste pentru utilizarea vertx-web, dar, deoarece se pare că a rezultat din optimizare, s-ar putea să se rezolve în versiunile ulterioare.