在前两个教程中对Vert.x开发Web应用已经有一个大概的了解,本章内容主要是讲述一些更深层次的内容,Vert.x的基本执行单元:Verticle。
我们从一个简单的Verticle入手,示例代码如下:
public class HelloVerticle extends AbstractVerticle {
private final Logger logger = LoggerFactory.getLogger(HelloVerticle.class);
private long counter = 1L;
@Override
public void start() {
// 创建一个定时作业
vertx.setPeriodic(5000, id -> logger.info("tick"));
// 创建一个http服务
vertx.createHttpServer()
.requestHandler(req -> {
logger.info("Request #{} from {}", counter++, req.remoteAddress().host());
req.response().end("Hello!");
}).listen(8888)
.onSuccess(server -> logger.info("HTTP server started on port: {}", server.actualPort()))
// Print the problem on failure
.onFailure(throwable -> logger.info("HTTP server start failure: {}", throwable.getMessage()));
}
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
//部署Verticle最简单的方式
vertx.deployVerticle(new HelloVerticle());
}
}
这段代码中我们创建了一个5秒的定时任务,打印一段日志,然后创建一个http的服务监听端口8888。运行main方法,运行结果如下:

从日志中可以看到,定时任务和Http服务的请求处理都是由vert.x-eventloop-thread-0完成的。
我们继续实验,修改代码如下所示,连续部署两个HelloVeticle
public class HelloVerticle extends AbstractVerticle {
private final Logger logger = LoggerFactory.getLogger(HelloVerticle.class);
private long counter = 1L;
@Override
public void start() {
// 创建一个定时作业
vertx.setPeriodic(5000, id -> logger.info("tick"));
// 创建一个http服务器
vertx.createHttpServer()
.requestHandler(req -> {
logger.info("Request #{} from {}", counter++, req.remoteAddress().host());
req.response().end("Hello!");
}).listen(8888)
.onSuccess(server -> logger.info("HTTP server started on port: {}", server.actualPort()))
// Print the problem on failure
.onFailure(throwable -> logger.info("HTTP server start failure: {}", throwable.getMessage()));
}
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
//部署Verticle最简单的方式
vertx.deployVerticle(new HelloVerticle());
vertx.deployVerticle(new HelloVerticle());
}
}
运行结果如下:

你可能会疑惑为什么没有端口占用冲突的错误。原因如下:
Vert.x 默认启用了 multiple event-loop threads
Vert.x 运行在一个 异步、事件驱动的模型 上,它使用了 多线程的事件循环。当你调用:
vertx.deployVerticle(new HelloVerticle());
vertx.deployVerticle(new HelloVerticle());
你实际上启动了两个 HelloVerticle 实例,并且 它们在不同的 event loop 线程上运行。
Vert.x 会自动处理端口共享
在 Vert.x 的 HttpServer 实现中,多个 Verticle 可以 共享同一个端口,而不会报端口占用错误。这是因为:
HttpServer 默认支持端口复用(端口共享)。HelloVerticle 监听同一个端口时,Vert.x 并不会为每个实例都创建独立的服务器,而是让它们共享 同一个底层的 HTTP 服务器。HelloVerticle 会被轮询调度来处理不同的请求。请求会被多个 Verticle 处理
由于多个 HelloVerticle 共享同一个 HTTP 服务器,当有请求进来时,它们会被 不同的 Verticle 实例轮流处理。这就像一个负载均衡器一样,分摊了 HTTP 请求的处理负载。
由上面两个实验,我们基本可以知道:一个Verticle实例运行在同一个线程上,我们可以安全的更新counter字段,我们不需要对counter进行任何同步操作,哪怕是在多线程环境下。