【问题标题】:Vertx JDBC how it works under the hoodVertx JDBC 如何在后台工作
【发布时间】:2018-10-30 02:59:53
【问题描述】:

我已经使用 Vertx 3 个月了,但现在我想知道非阻塞 Vertx JDBC 是如何工作的,例如

private void selectEndedMatches(){
        this.jdbcClient.getConnection(conn->{
            if(conn.failed()){
                log.error("Can't get Vertx connection",conn.cause());
            } else{
                final SQLConnection connection = conn.result();
                connection.queryWithParams("select matchid from get5_stats_matches where matchid > ? and end_time is not null",new JsonArray().add(this.lastMatchId),this::endedMatches);
                connection.close();
            }
        });
    }


private void endedMatches(final AsyncResult<ResultSet> rs) {
        if(rs.failed()){
            log.error("Can't make select statement from JdbcVerticle",rs.cause());
        } else{
            final List<JsonArray> results = rs.result().getResults();
            final List<Integer> endedMatches = new ArrayList<>(results.size());
            for (final JsonArray result : results) {
                endedMatches.add(result.getInteger(0));
            }

        }
    }

这里我们提供了一个回调,当我们的 select 语句从 DB 返回结果时会执行该回调,但它是如何工作的。

我在文档 https://vertx.io/docs/vertx-jdbc-client/java/ 中没有找到答案

在我看来:

Vertx 使用其中一个工作线程执行 select 语句以不阻塞事件循环线程。但是在这种情况下,每个 sql 查询都需要一个单独的线程来执行。 但是如果 Vertx 不使用任何单独的线程来执行查询怎么办,在这种情况下,事件循环如何知道结果何时来自 DB,使用线程非常简单,事件循环可以检查 jdbc 查询使用的线程的当前状态,并且如果状态已准备好,则意味着事件循环应该执行回调

我说的对吗?

【问题讨论】:

    标签: java asynchronous jdbc vert.x


    【解决方案1】:

    总的来说,你是对的。
    您可以自己查看引擎盖下的内容:

    方法queryWithParams()调用execute()

    public SQLConnection queryWithParams(String sql, JsonArray params, Handler<AsyncResult<ResultSet>> resultHandler) {
        new JDBCQuery(vertx, helper, options, ctx, sql, params).execute(conn, statementsQueue, resultHandler);
        return this;
      }
    

    execute() 看起来像这样:

    public void execute(Connection conn, TaskQueue statementsQueue, Handler<AsyncResult<T>> resultHandler) {
        ctx.executeBlocking(future -> handle(conn, future), statementsQueue, resultHandler);
    }
    

    您可能想知道ctx 来自哪里。在JDBCClientImpl:

    public SQLClient getConnection(Handler<AsyncResult<SQLConnection>> handler) {
        Context ctx = vertx.getOrCreateContext();
        getConnection(ctx, ar -> ctx.runOnContext(v -> handler.handle(ar)));
        return this;
      }
    

    你的查询是由普通的ExecutorService执行的

    【讨论】:

    • 非常感谢,您帮助了我解决与 Vertx 相关的大部分问题,但我能否请您不要创建其他主题。据我了解,Vertx 中的所有阻塞调用都是使用线程池实现的,但据我所知,vertx 在后台使用 Netty,这意味着更少的线程和更高的生产力,但在 vertx 中我没有看到它如何与没有线程的 blockig IO 一起使用游泳池
    • Netty 仅用于网络部分。阻止呼叫只是来自java.util.concurrent 的常见ThreadPools
    【解决方案2】:

    非阻塞 Vertx JDBC 是如何工作的?要知道这个答案,您需要深入了解 vertx 文档和非阻塞理论。

    让我们谈谈你的代码。

    connection.close();

    这行代码不是必需的。 Vertx 将按照他们的文档处理它。

    当我们使用 JDBC 执行查询时,使用 vertx,我们可以做以下两件事:

    1. 打开连接,依次执行多个查询,最后关闭连接,这是阻塞代码
    2. 打开连接,执行单个查询然后关闭连接,如果我们没有认真对待关闭连接,这是一种令人头疼的编码方式。

    现在让我们分析一下非阻塞 Vertx JDBC 是如何工作的。 如果我们更接近第 2 点,即 打开连接,执行单个查询,然后关闭连接。如果我们并行执行并认真关闭已经由 vertx 处理的连接,那么我们就实现了不完全但近似的非阻塞查询执行

    【讨论】:

      猜你喜欢
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-23
      相关资源
      最近更新 更多