Während Frameworks wie Spring Boot auf einem Thread-pro-Request-Modell basieren — jeder HTTP-Request blockiert einen Thread — setzt Eclipse Vert.x von Grund auf auf asynchrone, nicht-blockierende Verarbeitung. Das Ergebnis: eine einzige JVM-Instanz kann zehntausende parallele Verbindungen handhaben, ohne dass der Thread-Pool kollabiert.
Das Event-Loop-Modell
Vert.x basiert auf dem Reactor-Pattern: Ein oder mehrere Event-Loop-Threads verarbeiten eingehende Ereignisse (HTTP-Requests, Timer, Nachrichten) in einer Endlosschleife. Blockierende Operationen sind tabu — sie würden den gesamten Event-Loop lahmlegen.
Event Loop (Thread 1) --> Handler 1 --> Handler 2 --> DB (non-blocking) --> Resume
Event Loop (Thread 2) --> Handler 3 --> HTTP-Call (non-blocking) --> Resume
Event Loop (Thread N) --> Handler 4 --> Handler 5 --> Handler 6 --> Done
Grundbaustein: Das Verticle
Die Grundeinheit in Vert.x ist das Verticle — eine leichtgewichtige Komponente, die vom Event-Loop ausgeführt wird:
import io.vertx.core.VerticleBase;
import io.vertx.core.Future;
import io.vertx.ext.web.Router;
public class HttpServerVerticle extends VerticleBase {
@Override
public Future<?> start() {
Router router = Router.router(vertx);
router.get("/hello").handler(ctx -> {
ctx.response()
.putHeader("content-type", "text/plain")
.end("Hallo von Vert.x 5!");
});
return vertx.createHttpServer()
.requestHandler(router)
.listen(8080)
.onSuccess(server ->
System.out.println("Server läuft auf Port " + server.actualPort())
);
}
}
Code-Sprache: JavaScript (javascript)
Alle Handler-Callbacks werden vom Event-Loop ausgeführt — niemals blockieren!
Der Event Bus
Kommunikation zwischen Verticles erfolgt über den Event Bus, eine verteilte, lose gekoppelte Nachrichten-Infrastruktur:
<em>// Consumer-Verticle</em>
public class OrderVerticle extends VerticleBase {
@Override
public Future<?> start() {
vertx.eventBus().consumer("bestellung.neu", message -> {
String payload = (String) message.body();
System.out.println("Neue Bestellung: " + payload);
message.reply("Bestellung verarbeitet");
});
return Future.succeededFuture();
}
}
<em>// Producer-Verticle</em>
public class ProducerVerticle extends VerticleBase {
@Override
public Future<?> start() {
return vertx.eventBus().request("bestellung.neu", "B-1234")
.onSuccess(reply -> System.out.println("Antwort: " + reply.body()))
.onFailure(err -> System.err.println("Fehler: " + err.getMessage()));
}
}
Code-Sprache: PHP (php)
Der Event Bus unterstützt Publish/Subscribe, Request/Response und kann — mit Clustering — sogar JVM-übergreifend kommunizieren.
Nicht-blockierender Datenbankzugriff
Blockierende JDBC-Aufrufe sind im Event-Loop tödlich. Vert.x bietet mit dem SQL Client eine vollständig asynchrone Alternative:
import io.vertx.jdbcclient.JDBCPool;
import io.vertx.jdbcclient.JDBCConnectOptions;
import io.vertx.sqlclient.Pool;
import io.vertx.sqlclient.PoolOptions;
<em>// Pool anlegen</em>
JDBCConnectOptions connectOptions = new JDBCConnectOptions()
.setJdbcUrl("jdbc:postgresql://localhost:5432/shop");
PoolOptions poolOptions = new PoolOptions()
.setMaxSize(16);
Pool pool = JDBCPool.pool(vertx, connectOptions, poolOptions);
<em>// Asynchrone Query</em>
pool.query("SELECT * FROM produkte WHERE preis > 19.99")
.execute()
.onSuccess(rows -> {
for (var row : rows) {
System.out.println(row.getString("name"));
}
})
.onFailure(err -> {
System.err.println("Fehler: " + err.getMessage());
});
Code-Sprache: JavaScript (javascript)
Für PostgreSQL steht zudem der PgClient bereit — ein nativer, reaktiver Client, der ohne JDBC-Layer direkt über das PostgreSQL-Wire-Protokoll kommuniziert und seit Vert.x 5 über den PgBuilder konfiguriert wird.
Reaktive Alternativen: Mutiny und Virtual Threads
Neben RxJava unterstützt Vert.x 5 auch SmallRye Mutiny — eine eigenständige reaktive Programmierbibliothek, die als moderne Alternative zu RxJava positioniert ist. Mutiny bietet zwei Programmiermodelle: eine ereignisgesteuerte API (Multi/Uni) und eine imperative, Coroutine-ähnliche Variante.
Für Entwickler, die blockierende APIs anbinden müssen, bietet Vert.x seit dem Virtual-Threads-Incubator eine elegante Lösung: Blockierende Aufrufe können in virtuellen Threads ausgeführt werden, ohne den Event-Loop zu blockieren. Seit Java 21 sind Virtual Threads fester Bestandteil der Plattform:
vertx.executeBlocking(() -> {
<em>// Läuft in einem virtuellen Thread — blockierende Aufrufe sind hier sicher</em>
return legacyBlockingService.fetchData();
}).onSuccess(result -> {
<em>// Zurück im Event-Loop</em>
System.out.println("Ergebnis: " + result);
});
Code-Sprache: HTML, XML (xml)
Reaktive Streams mit RxJava
Vert.x lässt sich direkt mit RxJava kombinieren (Pull-Abhängigkeit vertx-rx-java3):
import io.vertx.rxjava3.core.AbstractVerticle;
import io.vertx.rxjava3.ext.web.Router;
public class RxVerticle extends AbstractVerticle {
@Override
public void start() {
Router router = Router.router(vertx);
router.get("/users/:id").handler(ctx -> {
String id = ctx.pathParam("id");
dbClient.preparedQuery("SELECT * FROM users WHERE id = $1")
.rxExecute(Tuple.of(Integer.parseInt(id)))
.map(rows -> rows.iterator().next())
.subscribe(
row -> ctx.response().end(row.toJson().encode()),
err -> ctx.fail(500, err)
);
});
}
}
Code-Sprache: JavaScript (javascript)
.rxExecute() wandelt das Future-basierte Vert.x-API in eine RxJava-Single um — für fließende reaktive Pipelines.
Wann Vert.x?
Vert.x ist besonders interessant für:
- Hochskalierende Echtzeit-Anwendungen (Chat, Gaming, Börsenticker)
- API-Gateways und Proxies mit minimalem Overhead
- Teams, die ein reaktives Modell mit leichtgewichtigem Toolkit einem Full-Stack-Framework vorziehen
- Polyglotte Projekte (Vert.x unterstützt Java, Kotlin, Groovy und JavaScript)
- Microservices mit nativer Unterstützung für OpenTelemetry, Health Checks und Circuit Breaker
Fazit
Vert.x ist kein Framework, sondern ein Toolkit: leichtgewichtig, unaufdringlich und extrem performant. Es zwingt Entwickler, in Ereignissen zu denken — blockierende Aufrufe sind strukturell unmöglich. Wer bereit ist, das Future-basierte Programmiermodell (oder RxJava) zu akzeptieren, wird mit einer Skalierbarkeit belohnt, die traditionelle Servlet-basierte Frameworks nicht erreichen. Mit der aktuellen Version 5.1.2 ist Vert.x erwachsen geworden — stabil, gut dokumentiert und produktionserprobt.