Quarkus

5 min

Quarkus je Kubernetes-Native Java framework prilagođen za GraalVM i HotSpot, sačinjen od najboljih Java biblioteka i standarda. Namera Quarkusa je da Javu načini vodećom platformom u Kubernetes i serverless okruženjima, a da u isto vreme ponudi programerima jedinstveni reaktivan i imperativan programerski model, koji optimalno adresira široki spektar distribuiranih arhitektura.

Vredi izdvojiti da Quarkus dolazi iz Crvenog Kapčeta (Red Hat); zbog naglaska na K8s i Openshift.

Java framework

Kao prvo, Quarkus je Java framework. Ne, u ovom slučaju nije “još-jedan”; prati standarde koje postoje u Javi i JEE i koristi poznate biblioteke koje je svako imao prilike da sretne. To značajno olakšava početak - zaparavo, skoro da i nema šta da se uči da bi se radilo sa Quarkusom.

Druga stvar je da se funkcionalnosti frameworka dodaju u projekat instaliranjem tkzv. ekstenzija. Instaliranje je puko dodavanje zavisnosti u build fajl na Quarkus biblioteku koja wrappuje postojeću biblioteku i time čini stvari još jednostavnijim za rad. Na primer, ukoliko treba uključiti RESTEasy JSON-B, instalira se io.quarkus:quarkus-resteasy-jsonb ekstenzija, koja sa sobom donosi sve zavisnosti i podešavanja, te je sve odmah spremno za rad.

Naravno, u projekat je moguće uključiti i 3rd party biblioteke koje nemaju svoju Quarkus ekstenziju. To radi očekivano bez problema - osim ako ne koristite Graal; više o tome kasnije.

Evo nekih primera kako izgleda raditi sa Quarkusom.

Konfiguracioni parametri koriste Microprofile:

@ConfigProperty(name = "greetings.message")
String message;

Dependency Injection je dat kroz CDI v2.0 subset - nepotpuna, ali dovoljna implementacija:

@ApplicationScoped
public class HelloService {}
...
@Inject
HelloService greetingService;

JSON je dan kroz JSONB:

@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response create(Sauce sauce) {
};

Perzistencija ispod ima JPA, Hibernate i Panache

@Entity
public class Cloud extends PanacheEntity {}
...
Cloud cloud = new Cloud("Fluffy");
cloud.persist();
Cloud.findAll().list();

Tu su još ekstenzije za REST klijenta, validaciju (Hibernate Validator); a postoji opcija za Reactive programming kroz MicroProfile spec, logovanje…

Poslednja stvar na koju bih skrenu pažnju je class-reloading u dev modu rada. Naime, Quarkus aplikacija se (za sada) ne može startovati iz IDE-a (remote debugging radi, naravno). U toku razvoja Quarkus startovan u dev modu prati sve izmene na klasama, resursima, konfiguracijama. Izmene se rekompajliraju i aplikacija se restartuje. Sve ovo radi jako dobro, možda nešto najbolje takvo što sam do sada imao prilike do probam.

GraalVM

Važna činjenica je da je Quarkus optimizovan i prilagošen za GraalVM (i SubstrateVM). Šta to tačno znači?

Pa, od samog početka od kada se kreira kostur projekta, postoji način da se napravi native artifact - izvršni program aplikacije:

./mvnw clean package -Pnative

Izvršni program je značajno manji od uobičajenog fat-jara koji se inače kreira, i, jasno, radi mnogo brže. Zapravo, ceo Quarkus radi izuzetno brzo, bilo u uobičajenom ili native obliku!

Primera radi, startovanje servera i aplikacije, koje zna da bude notorno dugo, u slučaju Quarkusa traje:

INFO  [io.quarkus]] (main) Quarkus 0.14.0 started in 1.285s. Listening on: http://[::]:8080
INFO  [io.quarkus]] (main) Installed features: [cdi, jaeger, kubernetes, resteasy, resteasy-jsonb

a kao native kod:

INFO  [io.quarkus]] (main) Quarkus 0.14.0 started in 0.027s. Listening on: http://[::]:8080
INFO  [io.quarkus]] (main) Installed features: [cdi, jaeger, kubernetes, resteasy, resteasy-jsonb, smallrye-health, smallrye-opentracing]

Da, nije greška, server je startovan za 27 milisekundi. Da, Graal kida :)

Da li moramo negde da platimo za ovu brzinu? Naravno. Kompajliranje Graal-om u native kod zna da značajno potraje. To nije nešto što treba raditi u toku razvoja. Kako kod i broj biblioteka raste, vreme kompiranje native programa se drastično povećava. Zato njega treba ostaviti za produkciju.

Drugi problem je da sve ne-Quarkus zavisnosti nemaju garanciju da rade sa Graal-om. Naravno, u većini slučajeva to nije problem, no dešava se da neka biblioteka prosto ne može da se kompajlira u native kod.

Nazad na optimizaciju: ne čini je samo native kod. Tu su i druge optimizacije, kao na primer analiza metapodataka prilikom kompajliranja i zamena refleksija konkretnim pozivima (gde je moguće) itd. Sve to bi trebalo da proizvede optimizovaniji kod, čak i kada se izvršava u osnovnom obliku, kao Java jar.

Docker, K8s, OpenShift

U kosturu projekta su uključeni i Dockerfile za java i native Docker imidž. Pored toga, Quarkus ima ekstenzije koje daje uobičajene funkcije u cloud okruženju. Tako na primer, postoji metrika (MicroProfile), trejsovanje izvršavanja (OpenTracing, Jaeger), Health Checks… Ponavljam, svaka se dodaje instaliranjem Quarkus ekstenzije. Podešavanja se pišu u application.properties.

Ostatak priče nema posebnosti koje su vezane za Quarkus. Igre radi, napravio sam Docker imidž i deploy-ovao ga na lokalni minishift:

# create new project
oc new-project quarkus --display-name="Hello Quarkus App"

# Create new binary
oc new-build --binary --name=hello-quarkus -l app=hello-quarkus

# Update Dockerfile location
oc patch bc/hello-quarkus -p '{"spec":{"strategy":{"dockerStrategy":{"dockerfilePath":"src/main/docker/Dockerfile.native"}}}}'

# Start build by pushing the Quarkus app to OpenShift
oc start-build hello-quarkus --from-dir=. --follow

# Deploy it as an OpenShift app
oc new-app --image-stream=quarkus/hello-quarkus

# Expose services
oc expose service hello-quarkus
oc get route

Ništa novo.

Zašto Quarkus?

Quarkus je još mlada platforma; intenzivno se radi na njoj. Možda je najbolji odgovor na pitanje “Zašto?” upravo sledeći citat:

Not trying to reinvent the enterprise world, and using familiar technology, but with a highly-optimized implementation.

Brzina i lakoća razvoja, ekstenzije i Graal čine ga vrlo zanimljivim za razvoj. Nedostatak je, možda, vezivanje za vendora, te razvoj i širenje fukncionalnosti zavisi od njega i open-source zajednice.

GitHub: hello-quarkus

🧧
Nisam definisan svojim stavovima. Stavove usvajamo, menjamo, nadograđujemo, ali oni ne čine nas same. Manje je važno da li se slažemo, koliko da se razumemo.