【发布时间】:2016-02-27 19:12:44
【问题描述】:
我正在使用 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 选择是异步的,让框架在等待选择查询返回任何内容时处理第二个连接不是一个公平的期望吗?
【问题讨论】:
-
TLDR:对于长时间运行的阻塞任务,策略是切换到后台线程池(经典多线程),它不使用与事件循环相同的线程以避免阻塞。