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());
  }
});

组合

  1. 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)
  });
  1. 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 中文翻译文档