Vert.x 事件循环 - 这如何异步?
我正在使用Vert.x,并且对基于事件循环而不是线程/连接模型的服务器非常陌生。
public void start(Future<Void> fut) {
vertx
.createHttpServer()
.requestHandler(r -> {
LocalDateTime start = LocalDateTime.now();
System.out.println("Request received - "+start.format(DateTimeFormatter.ISO_DATE_TIME));
final MyModel model = new MyModel();
try {
for(int i=0;i<10000000;i++){
//some simple operation
}
model.data = start.format(DateTimeFormatter.ISO_DATE_TIME) +" - "+LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
r.response().end(
new Gson().toJson(model)
);
})
.listen(4568, result -> {
if (result.succeeded()) {
fut.complete();
} else {
fut.fail(result.cause());
}
});
System.out.println("Server started ..");
}
- 我只是尝试模拟一个长时间运行的请求处理程序,以了解此模型的工作原理。
- 我观察到的是,所谓的事件循环被阻止,直到我的第一个请求完成。无论花费多少时间,后续请求在前一个请求完成之前都不会被执行。
- 显然,我在这里遗漏了一块,这就是我在这里的问题。
根据到目前为止的答案进行编辑:
- 接受所有请求不被认为是异步的吗?如果只有在清除前一个连接时才能接受新连接,那么它是如何异步的?
- 假设一个典型的请求需要 100 毫秒到 1 秒之间的任何时间(基于请求的类型和性质)。这意味着,在上一个请求完成之前,事件循环不能接受新连接(即使它在一秒钟内结束)。如果我作为一个程序员必须仔细考虑所有这些,并将这些请求处理程序推送到工作线程,那么它与线程/连接模型有什么不同?
- 我只是试图了解这个模型如何比传统的线程/连接服务器模型更好?假设没有 I/O 操作或所有 I/O 操作都是异步处理的?它如何解决c10k问题,当它不能并行启动所有并发请求并且必须等到前一个请求终止时?
-
即使我决定将所有这些操作推送到工作线程(池化),那么我又回到了同样的问题,不是吗?线程之间的上下文切换?编辑并顶上这个问题以获得赏金
- 不完全了解此模型如何声明为异步模型。
- Vert.x有一个异步JDBC客户端(Asyncronous是关键字),我试图用RXJava适应它。
- 下面是一个代码示例(相关部分)
server.requestStream().toObservable().subscribe(req -> {
LocalDateTime start = LocalDateTime.now(); System.out.println("Request for " + req.absoluteURI() +" received - " +start.format(DateTimeFormatter.ISO_DATE_TIME)); jdbc.getConnectionObservable().subscribe( conn -> { // Now chain some statements using flatmap composition Observable<ResultSet> resa = conn.queryObservable("SELECT * FROM CALL_OPTION WHERE UNDERLYING='NIFTY'"); // Subscribe to the final result resa.subscribe(resultSet -> { req.response().end(resultSet.getRows().toString()); System.out.println("Request for " + req.absoluteURI() +" Ended - " +LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)); }, err -> { System.out.println("Database problem"); err.printStackTrace(); }); }, // Could not connect err -> { err.printStackTrace(); } ); }); server.listen(4568);
- 其中的选择查询大约需要 3 秒才能返回完整的表转储。
- 当我触发并发请求(仅使用2个请求)时,我看到第二个请求完全等待第一个请求完成。
- 如果 JDBC 选择是异步的,那么让框架在等待选择查询返回任何内容时处理第二个连接难道不是一个公平的期望吗?