java - vertx如何创建eventloop线程
问题描述
我试过DeploymentOptions.setEventLoopPoolSize(even number x)
了,但它实际上创建了 x/2 个线程,奇数是可以的。
代码很简单,如下所示:
public final class Bootstrap {
private static final VertxOptions VERTX_OPTIONS;
private static final Vertx VERTX;
private static final DeploymentOptions HTTP_SERVER_DEPLOYMENT_OPTIONS;
static {
VERTX_OPTIONS = new VertxOptions();
VERTX_OPTIONS.setEventLoopPoolSize(22);
System.out.println("Event Loop Pool Size: " + VERTX_OPTIONS.getEventLoopPoolSize());
VERTX = Vertx.vertx(VERTX_OPTIONS);
HTTP_SERVER_DEPLOYMENT_OPTIONS = new DeploymentOptions();
HTTP_SERVER_DEPLOYMENT_OPTIONS.setInstances(24);
HTTP_SERVER_DEPLOYMENT_OPTIONS.setWorkerPoolName("http-server-worker");//remove this line you can create the right number of thread
}
public static void main(String[] args) {
VERTX.deployVerticle(MyHttpServer.class, HTTP_SERVER_DEPLOYMENT_OPTIONS, ar -> {
System.out.println("success");
System.out.println("is Worker? " + HTTP_SERVER_DEPLOYMENT_OPTIONS.isWorker());
});
}
}
public class MyHttpServer extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
Router router = Router.router(vertx);
String content = "I'm " + this + " thread: " + Thread.currentThread() + " router: " + router;
router.get("/").handler(context -> {
context.response().end(content);
});
vertx.createHttpServer().requestHandler(router).listen(80, ar -> {
if(ar.succeeded()) {
System.out.println("server start " + this);
startPromise.complete();
} else {
ar.cause().printStackTrace();
}
});
}
}
wertx-web 3.9.2
打开 Java VisualVM 可以看到设置和不设置 WorkerPoolName 的区别。
Java visualVM image
设置时,EventLoopPoolSize为偶数,实际创建的线程数减半。怎么了setWorkerPoolName()
?
解决方案
我阅读了源代码并发现该方法
private static EventLoop getEventLoop(VertxInternal vertx) in io.vertx.core.impl.ContextImpl
有个有趣的行为:不管是谁调用这个方法,它都会一个接一个地从一个数组中给你一个EventLoop对象。它实际上是在io.netty.util.concurrent.DefaultEventExecutorChooserFactory.GenericEventExecutorChooser这个内部类中实现的,它有一个方法next ()
@Override
public EventExecutor next() {
return executors[Math.abs(idx.getAndIncrement() % executors.length)];
}
因此,当您为 EventLoop 创建线程,并准确获取所有对应于偶数(或奇数)索引的 EventLoop 时,将会丢失一半的 EventLoop 数组。
而且,当 vertx 部署 verticles 时,它会查看你是否设置了 WorkerPoolName:
for (Verticle verticle: verticles) {
WorkerExecutorInternal workerExec = poolName != null ? vertx.createSharedWorkerExecutor(poolName, options.getWorkerPoolSize(), options.getMaxWorkerExecuteTime(), options.getMaxWorkerExecuteTimeUnit()) : null;
WorkerPool pool = workerExec != null ? workerExec.getPool() : null;
ContextImpl context = (ContextImpl) (options.isWorker() ? vertx.createWorkerContext(options.isMultiThreaded(), deploymentID, pool, conf, tccl) :
vertx.createEventLoopContext(deploymentID, pool, conf, tccl));
如果你这样做了,它将为此步骤创建 2 个上下文。这意味着它将调用 getEventLoop() 方法两次以获取每个 Context 的 EventLoop。综上所述,如果设置了poolName,每个Verticle在部署的时候会得到两次EventLoop,但是只会创建一个线程。
不知道是不是bug,因为刚接触vertx两天,也不知道是不是故意设计的。我就是想通过setEventLoopPoolSize()来控制我的线程数方法。
推荐阅读
- swiftui - SwiftUI 中选取器和表单的奇怪行为
- php - 无法读取文件名输入yii2
- firebase - 如何检查传入的数字数据是否大于或小于 Firestore 安全规则中的某个限制?
- python - 如何在运行时更新包含在变量 V1 中的变量 V2
- nunit - nunit 3 在命令行上测试为 nunit 2.6.4
- kubernetes - 防止K8S HPA在减少负载后删除pod
- c# - .Net HttpClient.timeout 是什么意思?
- javascript - 如何摆脱页面上不必要的 ng-container 边距?
- c++ - 我不明白我在使用 sse 的代码中哪里有问题
- reactjs - 有没有办法使用 useRef() 在 React 函数组件中缓存来自 redux 连接的数据?