Java Vert.x多线程web套接字
我有简单的vert.x应用程序:Java Vert.x多线程web套接字,java,vert.x,Java,Vert.x,我有简单的vert.x应用程序: public class Main { public static void main(String[] args) { Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(40).setInternalBlockingPoolSize(40)); Router router = Router.router(vertx); long main_pid = Threa
public class Main {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(40).setInternalBlockingPoolSize(40));
Router router = Router.router(vertx);
long main_pid = Thread.currentThread().getId();
Handler<ServerWebSocket> wsHandler = serverWebSocket -> {
if(!serverWebSocket.path().equalsIgnoreCase("/ws")){
serverWebSocket.reject();
} else {
long socket_pid = Thread.currentThread().getId();
serverWebSocket.handler(buffer -> {
String str = buffer.getString(0, buffer.length());
long handler_pid = Thread.currentThread().getId();
log.info("Got ws msg: " + str);
String res = String.format("(req:%s)main:%d sock:%d handlr:%d", str, main_pid, socket_pid, handler_pid);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
serverWebSocket.writeFinalTextFrame(res);
});
}
};
vertx
.createHttpServer()
.websocketHandler(wsHandler)
.listen(8080);
}
}
公共类主{
公共静态void main(字符串[]args){
Vertx Vertx=Vertx.Vertx(新的VertxOptions().setWorkerPoolSize(40).setInternalBlockingPoolSize(40));
路由器=路由器。路由器(vertx);
long main_pid=Thread.currentThread().getId();
Handler wsHandler=serverWebSocket->{
如果(!serverWebSocket.path().equalsIgnoreCase(“/ws”)){
serverWebSocket.reject();
}否则{
长套接字_pid=Thread.currentThread().getId();
serverWebSocket.handler(缓冲区->{
String str=buffer.getString(0,buffer.length());
long handler_pid=Thread.currentThread().getId();
log.info(“Got-ws-msg:+str”);
String res=String.format(“(请求:%s)主:%d套接字:%d句柄:%d”,str,主pid,套接字pid,处理程序pid);
试一试{
睡眠(500);
}捕捉(中断异常e){
e、 printStackTrace();
}
serverWebSocket.writeFinalTextFrame(res);
});
}
};
顶点
.createHttpServer()
.websocketHandler(wsHandler)
.听(8080);
}
}
当我将此服务器与多个客户端连接时,我看到它在一个线程中工作。但我想并行处理每个客户端连接。如何更改此代码以执行此操作?此:
新建VertxOptions().setWorkerPoolSize(40).setInternalBlockingPoolSize(40)
看起来您正在尝试创建自己的HTTP连接池,这可能不是您真正想要的
Vert.x
和其他基于非阻塞事件循环的框架的思想是,我们不尝试1线程->1连接
关联,而是在请求时,当前由事件循环线程提供服务的线程正在等待IO(例如来自DB的响应),该事件循环线程将被释放以服务于另一个连接。然后,这允许单个事件循环线程以类似并发的方式为多个连接提供服务
如果您希望充分利用计算机上的所有核心,并且只运行一个垂直卷
,则将实例数设置为部署垂直卷时的核心数
即
x是一个框架,这意味着它使用单线程模型来处理所有应用程序负载。此模型比线程模型具有更好的伸缩性
要知道的关键点是,放入处理程序中的所有代码必须永远不要阻塞(就像线程.sleep
),因为它会阻塞主线程。如果您有阻塞代码(例如JDBC调用),则应将阻塞代码包装在executingBlocking
处理程序中,例如:
serverWebSocket.handler(buffer -> {
String str = buffer.getString(0, buffer.length());
long handler_pid = Thread.currentThread().getId();
log.info("Got ws msg: " + str);
String res = String.format("(req:%s)main:%d sock:%d handlr:%d", str, main_pid, socket_pid, handler_pid);
vertx.executeBlocking(future -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
serverWebSocket.writeFinalTextFrame(res);
future.complete();
});
});
现在,所有阻塞代码都将在线程池中的一个线程上运行,您可以对该线程池进行配置,如其他回复中所示
如果您希望避免写入所有这些执行阻塞处理程序,并且您知道需要进行多个阻塞调用,那么您应该考虑使用A,因为它们将在事件总线级别上缩放。
多线程的最后一个注意事项是,如果您使用多线程,您的服务器的效率将不如单个线程,例如,在现代机器上发生1000万线程事件后,它将无法处理1000万WebSocket(我们在2016年)将使您的操作系统调度程序屈服。我会将其包装在一个Verticle
中,并使用DeploymentOptions.setInstances()
多次启动Verticle
。我可以提供一个例子,如果这就是你想要的。谢谢你,这正是我已经做的)。只是犹豫。请考虑一下威尔的回答。您可能应该看看异步I/O。
serverWebSocket.handler(buffer -> {
String str = buffer.getString(0, buffer.length());
long handler_pid = Thread.currentThread().getId();
log.info("Got ws msg: " + str);
String res = String.format("(req:%s)main:%d sock:%d handlr:%d", str, main_pid, socket_pid, handler_pid);
vertx.executeBlocking(future -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
serverWebSocket.writeFinalTextFrame(res);
future.complete();
});
});