Vert.x 学习笔记2 事件驱动
Vert.x 事件驱动
一些解释
Don’t call us, we’ll call you
通过这句话我理解vertx 推崇的事件模型 都是异步交互,并且在完成事件以后通过广播方式通知到其他服务
但是我有一个疑问,如果都是异步驱动的话我如何将错误信息抛给前端,他是如果管理http 上下文的,估计文档后面有解答?
- 贴一些官网的示例代码
// 这个处理器将会每隔一秒被调用一次
vertx.setPeriodic(1000, id -> {
System.out.println("timer fired!");
});
// 服务器每次收到一个HTTP请求时这个处理器将被调用
server.requestHandler(request -> {
request.response().end("hello world!");
});
eventLoop
- 在多数情况下,Vert.x使用被称为 Event Loop 的线程来调用您的处理器。
- 由于Vert.x或应用程序的代码块中没有阻塞代码,Event Loop 可以在事件到达时快速地分发到不同的处理器中。
- 由于没有阻塞代码,Event Loop 可在短时间内分发大量的事件。 例如,一个单独的 Event Loop 可以非常迅速地处理数千个 HTTP 请求。
- 我们称之为 Reactor 模式(译者注:Reactor Pattern 翻译成了 反应器模式)。
- Vert.x的工作方式有所不同。每个 Vertx 实例维护的是 多个Event Loop 线程。 默认情况下,我们会根据机器上可用的核数量来设置 Event Loop 的数量,您亦可自行设置。
- 我们将这种模式称为 Multi-Reactor 模式(多反应器模式),区别于单线程的 Reactor 模式(反应器模式)。
尽管Vert.x 的 API 都是非阻塞式的,且不会阻塞 Event Loop, 但是用户编写的处理器中可能会阻塞 Event Loop。
如果这样做,该 Event Loop 在被阻塞时就不能做任何事情;如果您阻塞了 Vertx 实例中的所有Event Loop,那么您的应用就会完全停止!
- Thead.sleep()
- 等待一个锁
- 等待一个互斥信号或监视器(例如同步的代码块)
- 执行一个长时间数据库操作并等待其结果
- 执行一个复杂的计算,占用了可感知的时长
- 在循环语句中长时间逗留
future
future的异步结果
Vert.x 4使用future承载异步结果。
异步的方法会返回一个 Future对象,其包含 成功 或 失败 的异步结果。
我们不能直接操作future的异步结果,而应该设置future的handler; 当future执行完毕,结果可用时,会调用handler进行处理。
FileSystem fs = vertx.fileSystem();
Future<FileProps> future = fs.props("/my_file.txt");
future.onComplete((AsyncResult<FileProps> ar) -> {
if (ar.succeeded()) {
FileProps props = ar.result();
System.out.println("File size = " + props.size());
} else {
System.out.println("Failure: " + ar.cause().getMessage());
}
});
组合
- future 是可以组合的,future 可以是如下串行的,一个future 成功后执行一段新的future
这里例子中,有三个操作被串起来了 详细的加到了注释中
如果这三个步骤全部成功,则最终的 Future(future)会是成功的; 其中任何一步失败,则最终 Future 就是失败的。
FileSystem fs = vertx.fileSystem();
Future<Void> future = fs
.createFile("/foo") //第一个future 一个文件被创建(createFile)
.compose(v -> {
return fs.writeFile("/foo", Buffer.buffer()); //第二个future 一些东西被写入到文件(writeFile)
})
.compose(v -> {
return fs.move("/foo", "/bar"); // 第三个future 文件被移走(move)
});
- future 可以是互相协作的
如下代码两个future被并行的执行,all方法会等待两个future 都异步返回后执行新的handler处理,这些操作都会是async的。
Future<HttpServer> httpServerFuture = httpServer.listen();
Future<NetServer> netServerFuture = netServer.listen();
CompositeFuture.all(httpServerFuture, netServerFuture).onComplete(ar -> {
if (ar.succeeded()) {
// 所有服务器启动完成
} else {
// 有一个或多个服务器启动失败
}
});
同样它存在any方法,任意一个成功了,future 就会成功!
CompositeFuture.any(future1, future2).onComplete(ar -> {
if (ar.succeeded()) {
// 至少一个成功
} else {
// 所有的都失败
}
});
join 方法等待所有方法被执行无论有没有失败的
个人理解和all 的区别应该是all 只要有一个失败了,其他操作 会被终止。
CompositeFuture.join(future1, future2, future3).onComplete(ar -> {
if (ar.succeeded()) {
// 所有都成功
} else {
// 全部完成(无论成功还是失败),且至少一个失败
}
});
转载自 vertx 中文翻译文档