gpt4 book ai didi

java - Vertx http 服务器线程已被阻塞 xxxx 毫秒,时间限制为 2000

转载 作者:可可西里 更新时间:2023-11-01 17:32:11 24 4
gpt4 key购买 nike

我已经使用 编写了一个大型 HTTP 服务器,但是当并发请求数增加时出现此错误

 WARNING: Thread Thread[vert.x-eventloop-thread-1,5,main] has been blocked for 8458 ms, time limit is 1000

io.vertx.core.VertxException: 线程阻塞

这是我的完整代码:

  public class MyVertxServer {

public Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(100));
private HttpServer server = vertx.createHttpServer();
private Router router = Router.router(vertx);

public void bind(int port){


server.requestHandler(router::accept).listen(port);

}

public void createContext(String path,MyHttpHandler handler){

if(!path.endsWith("/")){
path += "/";
}

path+="*";


router.route(path).handler(new Handler<RoutingContext>() {

@Override
public void handle(RoutingContext ctx) {

String[] handlerID = ctx.request().uri().split(ctx.currentRoute().getPath());

String suffix = handlerID.length > 1 ? handlerID[1] : null;
handler.Handle(ctx, new VertxUtils(), suffix);

}
});
}


}

我怎么调用它:

    ver.createContext("/getRegisterManager",new ProfilesManager.RegisterHandler());
ver.createContext("/getLoginManager", new ProfilesManager.LoginHandler());
ver.createContext("/getMapcomCreator",new ItemsManager.MapcomCreator());
ver.createContext("/getImagesManager", new ItemsManager.ImagesHandler());

ver.bind(PORT);

我怎么没发现 eventbus() 对于处理发送/接收文件的 http 服务器有用,因为你需要在消息中发送 RoutingContext 是不可能的。

你能给我指明正确的方向吗?谢谢

添加了一些处理程序代码:

  class ProfileGetter implements MyHttpHandler{

@Override
public void Handle(RoutingContext ctx, VertxUtils utils, String suffix) {

String username = utils.Decode(ctx.request().headers().get("username"));
String lang = utils.Decode(ctx.request().headers().get("lang"));

display("profile requested : "+username);

Profile profile = ProfileManager.FindProfile(username,lang);

if(profile == null){
ctx.request().response().putHeader("available","false");
utils.sendResponseAndEnd(ctx.response(),400);
return;
}else{
ctx.request().response().putHeader("available","true");
utils.writeStringAndEnd(ctx, new Gson().toJson(profile));
}

}



}

此处 ProfileManager.FindProfile(username,lang) 在同一线程上执行长时间运行的数据库作业

...

基本上我所有的进程都发生在主线程上,因为如果我使用执行器,我会在 Vertx 中得到奇怪的异常和空指针,让我觉得 Vertx 中的请求处理器是并行的

最佳答案

考虑到问题中的少量代码,让我们同意问题出在线上:

Profile profile = ProfileManager.FindProfile(username,lang);

假设这是在内部进行一些阻塞 JDBC 调用,这是 Vert.x 中的反模式,您可以通过多种方式解决这个问题。

假设您可以完全重构 IMO 最好的 ProfileManager 类,然后您可以将其更新为响应式(Reactive),因此您的代码将如下所示:

ProfileManager.FindProfile(username,lang, res -> {
if (res.failed()) {
// handle error, sent 500 back, etc...
} else {
Profile profile = res.result();

if(profile == null){
ctx.request().response().putHeader("available","false");
utils.sendResponseAndEnd(ctx.response(),400);
return;
}else{
ctx.request().response().putHeader("available","true");
utils.writeStringAndEnd(ctx, new Gson().toJson(profile));
}
}
});

现在在幕后发生的事情是您的 JDBC 调用不会阻塞(这很棘手,因为 JDBC 本质上是阻塞的)。因此,要解决此问题,并且您很幸运能够使用 MySQL 或 Postgres,那么您可以针对 async-client 编写 JDBC 代码。如果您受困于其他 RDBMS 服务器,那么您需要使用 jdbc-client这反过来将使用线程池从事件循环线程中卸载工作。

现在假设您不能更改 ProfileManager 代码,那么您仍然可以通过将代码包装在 executeBlocking block 中将其卸载到线程池:

vertx.executeBlocking(future -> {
Profile profile = ProfileManager.FindProfile(username,lang);
future.complete(profile);
}, false, res -> {
if (res.failed()) {
// handle error, sent 500 back, etc...
} else {
Profile profile = res.result();

if(profile == null){
ctx.request().response().putHeader("available","false");
utils.sendResponseAndEnd(ctx.response(),400);
return;
}else{
ctx.request().response().putHeader("available","true");
utils.writeStringAndEnd(ctx, new Gson().toJson(profile));
}
}
});

关于java - Vertx http 服务器线程已被阻塞 xxxx 毫秒,时间限制为 2000,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39474808/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com