我来自一个请求 = 一个线程的概念,现在我想使用
Vertx
来理解事件循环的概念。根据文档,如果我们使用阻塞操作,我们应该将其传递给 executeBlocking
方法。
Verticles use the Vert.x worker pool for executing blocking actions, i.e executeBlocking or worker verticle.
我有一些与本段相关的问题
http://vertx.io/docs/vertx-core/groovy/
这是我的代码:
public class JdbcVertx extends AbstractVerticle{
public static void main(String[] args) {
Vertx v = Vertx.vertx();
v.deployVerticle(new JdbcVertx(),new DeploymentOptions().setWorkerPoolSize(10));
}
@Override
public void start() throws Exception {
JDBCClient client = JDBCClient.createNonShared(this.vertx, new JsonObject()
.put("url", "jdbc:postgresql://localhost:5432/test")
.put("user", "postgres")
.put("password", "pw")
.put("driver_class", "org.postgresql.Driver")
.put("max_pool_size", 30));
this.vertx.createHttpServer()
.requestHandler(r -> {
int i = (int) (Math.random() * 100);
System.out.println("Req id: " + i+ " "+Thread.currentThread().getName());
client.getConnection(handler -> {
if (handler.failed()) {
throw new RuntimeException(handler.cause());
} else {
final SQLConnection connection = handler.result();
this.vertx.executeBlocking(blockingCodeHandler->{
connection.execute(execute(), hndlr -> {
connection.close(closehndlr -> {
if (closehndlr.failed()) {
throw new RuntimeException(closehndlr.cause());
} else {
System.out.println("CON end: "+i+" "+Thread.currentThread().getName());
r.response().putHeader("content-type", "text/html").end("Response: " + i);
}
});
});
},false,as->{});
}
});
}).listen(8080);
}
private String execute(){
return "insert into rubbish (name) values ('test')";
}
我向 http 服务器发送 100 个请求,这是输出:
Req id: 45 vert.x-eventloop-thread-0
Req id: 22 vert.x-eventloop-thread-0
Req id: 96 vert.x-eventloop-thread-0
Req id: 85 vert.x-eventloop-thread-0
Req id: 33 vert.x-eventloop-thread-0
CON end: 22 vert.x-eventloop-thread-0
CON end: 33 vert.x-eventloop-thread-0
CON end: 45 vert.x-eventloop-thread-0
CON end: 85 vert.x-eventloop-thread-0
1)事件循环如何在请求之间切换(从输出中它首先获取一些请求,然后给它们响应)?
2)我使用
executeBlocking
方法,但是你如何看到上面的代码仅使用名为 vert.x-eventloop-thread-0
的事件循环线程
3)根据第一个问题,vertx事件循环在请求之间切换,但如果我将方法
execute
更改为:
private String execute(){
Thread.sleep(3000);
return "insert into rubbish (name) values ('test')";
}
它将停止事件循环,直到超时未完成
提前谢谢您
1)你可以这样看待EventLoop:每次你提供一个处理程序时,它都是另一个被放入排序队列中的函数。
当您收到第一个请求时,它可能看起来像这样
requestHandler (R1)
requestHandler (R2)
然后EventLoop将会 l 弹出队列中的第一个元素,并将其结果放回队列中:
requestHandler (R2)
getConnection (R1)
然后第三个请求可能会进来,而我们弹出
requestHandler (R2)
:
getConnection (R1)
requestHandler (R3)
getConnection (R2)
并且重复,因此
Loop
2)实际上,您在阻塞处理程序中没有执行任何操作。在
if (closehndlr.failed()) {
之前添加一些大循环,您会看到警告。
现在发生的事情是你正在做
async->sync->async
,并且你的同步基本上是0ms。
您可以通过以下代码看到这一点:
vertx.setPeriodic(1000, h -> {
System.out.println("Periodic on " + Thread.currentThread().getName());
vertx.executeBlocking(f -> {
System.out.println("Future on " + Thread.currentThread().getName());
f.complete();
}, r -> {
System.out.println("Result on " + Thread.currentThread().getName());
});
});
打印:
Periodic on vert.x-eventloop-thread-0
Future on vert.x-worker-thread-3
Result on vert.x-eventloop-thread-0
Periodic on vert.x-eventloop-thread-0
Future on vert.x-worker-thread-4
Result on vert.x-eventloop-thread-0
3) 不要使用
Thread.sleep(3000)
:) 通过这样做,你只需要求 EventLoop 停止 3 秒。您还应该看到有关此的警告。
添加参数“false”
vertx.executeBlocking(f -> {
System.out.println("Future on " + Thread.currentThread().getName());
f.complete();
}, false ,r -> {
System.out.println("Re enter code here`sult on " + Thread.currentThread().getName());
});