Vert.x SQLConnection:“路由中出现意外异常”,“等待30000(ms)答复后超时”

时间:2019-01-06 19:51:17

标签: java postgresql jdbc vert.x

我将Vert.x与PostgreSQL结合使用。

此刻,我正在尝试向数据库发出请求,但是由于某种原因,尽管从客户端收到了请求,但还是不满意。

我看到的错误看起来像这样:

enter image description here

奇怪的是,如果我关闭服务器并重新启动,请求将得到满足。

这使我认为这与到数据库“挂起”的一个连接有关,并阻止了此请求。

我可以设想的另一种可能性是路线会有些混乱,是吗?

路线如下:

Router router = Router.router(vertx);
router.post().handler(BodyHandler.create());
router.post("/create").handler(this::createHandler);
router.post("/login").handler(this::loginHandler);
router.post("/account").handler(this::accountHandler);
router.post("/invitation").handler(this::invitationHandler);
router.post("/initiate").handler(this::initiateHandler);

我有一个理论认为问题可能与向数据库发出多个请求的复合方法有关,因为执行此方法后总是会发生故障:

private void account(Message<JsonObject> message) {
    JsonArray username = new JsonArray().add(message.body().getString("username"));

    JsonObject response = new JsonObject();
    response.put("response", "account");

    friends(friendsResult -> {
        if (friendsResult.succeeded()) {
            response.put("friends", friendsResult.result());

            games(username, gamesResult -> {
                if (gamesResult.succeeded()) {
                    response.put("games", gamesResult.result());

                    invitations(username, invitationsResult -> {
                        if (invitationsResult.succeeded()) {
                            response.put("invitations", invitationsResult.result());

                            System.out.println("ACCOUNT RESPONSE: " + response.encodePrettily());

                            /* * */
                            message.reply(response);
                        } else {
                            System.out.println("FAILED IN <<INVITATIONS RESULT>>...");
                        }
                    });
                } else {
                    System.out.println("FAILED IN <<GAMES RESULT>>...");
                }
            });
        } else {
            System.out.println("FAILED IN <<FRIENDS RESULT>>...");
        }
    });
}

如上所述,它具有三种“帮助”方法,在这里...

一个:

private void friends(Handler<AsyncResult<List<String>>> handler) { // TODO: Replace w/ concept of <<friends>>...
    List<String> friends = new ArrayList<>();
    dbClient.queryStream(
            sqlQueries.get(SqlQuery.FETCH_FRIENDS),
            asyncResult -> {
                if (asyncResult.succeeded()) {
                    asyncResult.result().handler(row -> friends.add(row.getString(0)));
                }
                handler.handle(Future.succeededFuture(friends));
            });
    dbClient.close();
}

两个:

private void invitations(JsonArray params, Handler<AsyncResult<JsonObject>> handler) {
    JsonObject invitations = new JsonObject();
    params.add(false);
    JsonArray outboundArray = new JsonArray();
    dbClient.queryStreamWithParams(
            sqlQueries.get(SqlQuery.OUTBOUND_INVITATIONS),
            params,
            asyncResult0 -> {
                if (asyncResult0.succeeded()) {
                    asyncResult0.result().handler(row -> {
                        JsonObject invitation = new JsonObject();
                        invitation.put("identifier", row.getString(0));
                        invitation.put("user1", row.getString(1));
                        outboundArray.add(invitation);
                    });
                }
                invitations.put("outbound", outboundArray);

                JsonArray inboundArray = new JsonArray();
                dbClient.queryStreamWithParams(
                        sqlQueries.get(SqlQuery.INBOUND_INVITATIONS),
                        params,
                        asyncResult -> {
                            if (asyncResult.succeeded()) {
                                asyncResult.result().handler(row -> {
                                    JsonObject invitation = new JsonObject();
                                    invitation.put("identifier", row.getString(0));
                                    invitation.put("user0", row.getString(1));
                                    inboundArray.add(invitation);
                                });
                            }
                            invitations.put("inbound", inboundArray);

                            handler.handle(Future.succeededFuture(invitations));
                        });
            });
}

三:

private void games(JsonArray params, Handler<AsyncResult<JsonArray>> handler) {
    JsonArray games = new JsonArray();
    dbClient.queryStreamWithParams(
            sqlQueries.get(SqlQuery.FETCH_GAMES_0),
            params,
            asyncResult0 -> {
                if (asyncResult0.succeeded()) {
                    asyncResult0.result().handler(row -> {
                        JsonObject game = new JsonObject();
                        game.put("user0", params.getString(0));
                        game.put("user1", row.getString(1));
                        game.put("identifier", row.getString(0));
                        games.add(game);
                    });
                }
                dbClient.queryStreamWithParams(
                        sqlQueries.get(SqlQuery.FETCH_GAMES_1),
                        params,
                        asyncResult1 -> {
                            if (asyncResult1.succeeded()) {
                                asyncResult1.result().handler(row -> {
                                    JsonObject game = new JsonObject();
                                    game.put("user0", row.getString(1));
                                    game.put("user1", params.getString(0));
                                    game.put("identifier", row.getString(0));
                                    games.add(game);
                                });
                            }
                            handler.handle(Future.succeededFuture(games));
                        });
            });
}

这实际上是失败的请求:

private void gamestateRequest(Message<JsonObject> message) {
    JsonArray identifier = new JsonArray().add(message.body().getString("identifier"));

    dbClient.queryWithParams(
            sqlQueries.get(SqlQuery.GAMESTATE_REQUEST),
            identifier,
            asyncResult -> {
                if (asyncResult.succeeded()) {
                    ResultSet resultSet = asyncResult.result();

                    JsonObject response = new JsonObject();
                    String user0 = resultSet.getResults().get(0).getString(0);
                    String user1 = resultSet.getResults().get(0).getString(1);
                    String gamestate = resultSet.getResults().get(0).getString(2);

                    response.put("response", "gamestate");
                    response.put("user0", user0);
                    response.put("user1", user1);
                    response.put("gamestate", gamestate);

                    System.out.println("GAMESTATE REQUEST RESPONSE: " + response.encodePrettily());

                    message.reply(response);
                } else {

                    System.out.println("GAMESTATE REQUEST FAIL");

                    reportQueryError(message, asyncResult.cause());
                }
            });
    dbClient.close();
}

每个路由都与以下处理程序方法关联,如下所示:

private void handler(RoutingContext context, String headerValue) {
    LOGGER.info("RECEIVED CONTEXT: " + context.getBodyAsString());

    JsonObject data = new JsonObject(context.getBodyAsString());
    DeliveryOptions options = new DeliveryOptions().addHeader("action", headerValue);
    vertx.eventBus().send(dbQueue, data, options, reply -> {
        if (reply.succeeded()) {
            context.response()
                    .putHeader("content-type", "text/html")
                    .end(reply.result().body().toString());
        } else {

            System.out.println("FAIL IN <<handler>>...");

            context.fail(reply.cause());
        }
    });
}

也许这与EventBus有关?对于透视图,其配置如下:

@Override
public void start(Future<Void> future) throws Exception {
    loadSqlQueries(); // NOTE: This method call uses blocking APIs, but data is small...

    dbClient = PostgreSQLClient.createShared(vertx, new JsonObject()
            .put("username", "s.matthew.english")
            .put("password", "")
            .put("database", "s.matthew.english")
            .put("url", config().getString(CONFIG_JDBC_URL, "jdbc:postgresql://localhost:5432/wiki"))
            .put("driver_class", config().getString(CONFIG_JDBC_DRIVER_CLASS, "org.postgresql.Driver"))
            .put("max_pool_size", config().getInteger(CONFIG_JDBC_MAX_POOL_SIZE, 30)));

    dbClient.getConnection(connectionResult -> {
        if (connectionResult.succeeded()) {
            SQLConnection connection = connectionResult.result();
            connection.execute(sqlQueries.get(SqlQuery.CREATE_USERS_TABLE), createUsersTableResult -> {

                if (createUsersTableResult.succeeded()) {
                    connection.execute(sqlQueries.get(SqlQuery.CREATE_GAMES_TABLE), createGamesTableResult -> {
                        connection.close();

                        if (createGamesTableResult.succeeded()) {
                            vertx.eventBus().consumer(config().getString(CONFIG_QUEUE, "db.queue"), this::onMessage);
                            future.complete();
                        } else {
                            LOGGER.error("Database preparation error", createGamesTableResult.cause());
                            future.fail(createGamesTableResult.cause());
                        }
                    });
                } else {
                    LOGGER.error("Database preparation error", createUsersTableResult.cause());
                    future.fail(createUsersTableResult.cause());
                }
            });
        } else {
            LOGGER.error("Could not open a database connection", connectionResult.cause());
            future.fail(connectionResult.cause());
        }
    });
}

如果有帮助,很乐意提供更多详细信息/上下文。感谢您的考虑。

1 个答案:

答案 0 :(得分:0)

这与queryStreamWithParams有关,尽管我不知道到底是什么。最后,我像这样解决了它:

private void account(Message<JsonObject> message) {
    JsonArray params0 = new JsonArray().add(message.body().getString("username"));

    JsonArray games = new JsonArray();
    JsonArray friends = new JsonArray();
    JsonObject invitations = new JsonObject();
    JsonArray outboundArray = new JsonArray();
    JsonArray inboundArray = new JsonArray();
    JsonObject response = new JsonObject();
    response.put("response", "account");

    String query0 = "select identifier, user1 from games where accepted = 'true' and user0 = ?";
    dbClient.queryWithParams(query0, params0, res0 -> {
        if (res0.succeeded()) {
            ResultSet resultSet0 = res0.result();
            List<String> pages0a = resultSet0.getResults()
                    .stream()
                    .map(json -> json.getString(0))
                    .sorted()
                    .collect(Collectors.toList());
            List<String> pages0b = resultSet0.getResults()
                    .stream()
                    .map(json -> json.getString(1))
                    .sorted()
                    .collect(Collectors.toList());
            for (int i = 0; i < pages0a.size(); i++) {
                JsonObject game = new JsonObject();
                game.put("user0", message.body().getString("username"));
                game.put("user1", pages0b.get(i));
                game.put("identifier", pages0a.get(i));
                games.add(game);
            }
            String query1 = "select identifier, user0 from games where accepted = 'true' and user1 = ?";
            dbClient.queryWithParams(query1, params0, res1 -> {
                if (res1.succeeded()) {
                    ResultSet resultSet1 = res1.result();
                    List<String> pages1a = resultSet1.getResults()
                            .stream()
                            .map(json -> json.getString(0))
                            .sorted()
                            .collect(Collectors.toList());
                    List<String> pages1b = resultSet1.getResults()
                            .stream()
                            .map(json -> json.getString(1))
                            .sorted()
                            .collect(Collectors.toList());
                    for (int i = 0; i < pages1a.size(); i++) {
                        JsonObject game = new JsonObject();
                        game.put("user0", pages1b.get(i));
                        game.put("user1", message.body().getString("username"));
                        game.put("identifier", pages1a.get(i));
                        games.add(game);
                    }
                    String query2 = "select username from users";
                    dbClient.query(query2, res2 -> {
                        if (res2.succeeded()) {
                            ResultSet resultSet2 = res2.result();
                            List<String> pages2 = resultSet2.getResults()
                                    .stream()
                                    .map(json -> json.getString(0))
                                    .sorted()
                                    .collect(Collectors.toList());
                            for(String page : pages2) {
                                friends.add(page);
                            }

                            String query3 = "select identifier, user1 from games where user0 = ? and accepted = ?";
                            JsonArray params3 = new JsonArray().add(message.body().getString("username")).add(false);
                            dbClient.queryWithParams(query3, params3, res3 -> {
                                if (res3.succeeded()) {
                                    ResultSet resultSet3 = res3.result();
                                    List<String> pages3a = resultSet3.getResults()
                                            .stream()
                                            .map(json -> json.getString(0))
                                            .sorted()
                                            .collect(Collectors.toList());
                                    List<String> pages3b = resultSet3.getResults()
                                            .stream()
                                            .map(json -> json.getString(1))
                                            .sorted()
                                            .collect(Collectors.toList());
                                    for (int i = 0; i < pages3a.size(); i++) {
                                        JsonObject invitation = new JsonObject();
                                        invitation.put("identifier", pages3a.get(i));
                                        invitation.put("user1", pages3b.get(i));
                                        outboundArray.add(invitation);
                                    }
                                    String query4 = "select identifier, user0 from games where user1 = ? and accepted = ?";
                                    dbClient.queryWithParams(query4, params3, res4 -> {
                                        if (res4.succeeded()) {
                                            ResultSet resultSet4 = res4.result();
                                            List<String> pages4a = resultSet4.getResults()
                                                    .stream()
                                                    .map(json -> json.getString(0))
                                                    .sorted()
                                                    .collect(Collectors.toList());
                                            List<String> pages4b = resultSet4.getResults()
                                                    .stream()
                                                    .map(json -> json.getString(1))
                                                    .sorted()
                                                    .collect(Collectors.toList());
                                            for (int i = 0; i < pages4a.size(); i++) {
                                                JsonObject invitation = new JsonObject();
                                                invitation.put("identifier", pages4a.get(i));
                                                invitation.put("user0", pages4b.get(i));
                                                inboundArray.add(invitation);
                                            }
                                            /* * */
                                            response.put("friends", friends);
                                            response.put("games", games);
                                            invitations.put("outbound", outboundArray);
                                            invitations.put("inbound", inboundArray);
                                            response.put("invitations", invitations);
                                            /* * */
                                            message.reply(response);
                                        } else {
                                            // Failed!
                                        }
                                    });
                                } else {
                                    // Failed!
                                }
                            });
                        } else {
                            // Failed!
                        }
                    });
                } else {
                    // Failed!
                }
            });
        } else {
            // Failed!
        }
    });

}

^如果您有一个如何将其重构为更简洁的想法,我将不胜感激。