java - 异步和同步模式的并发

标签 java multithreading vert.x

我们有一个基于servlet的应用程序,它同步服务请求,每个请求将花费近4000ms,因为它必须对远程数据库执行大量sql查询并进行大量计算工作机会。

我们使用ab来测试应用程序,并发度和吞吐量都比较小。

在我看来,在传统的 servlet 模型中,请求是同步处理的:为每个请求创建一个线程,并且该线程将等待,直到该过程完成,这意味着在我的情况下,该 servlet 线程将等待4000ms,在挂起期间,它不能做任何事情。一种资源浪费。

有时,我对vertx感兴趣,所以我基于vertx编写了应用程序。我知道vertx中的事件循环模型无法被阻止。因此, block 作业(需要4000ms)在工作线程中执行,如下所示:

router.route().blockingHandler(context -> {
    List result=new ArrayList();


    String[] layers = getLayers(context);
    final int[] len=new int[]{layers.length};
    layers.forEach(l_>{
        context.vertx().executeBlocking(f->{
            List d = doDataseJob(l);
            d = doCalculationJob(d)
            f.complete(d);
        },false,r->{
            len[0]--;
            result.addAll(r.result())
            if(len[0]==0){
                //all blocking jobs have done
                //return
                context.response().end(.......);
            }
        });
    });
});

但是再次通过ab测试并发性后,我们发现与基于servlet的应用程序相比,只有一点点的改进。

据我所知,异步模式和同步模式下单个请求的响应时间不会有太大变化,但是异步模式下的吞吐量并发应该有所提高(基于 vertx 的应用程序),因为仅转发请求的事件循环线程可以比以前处理更多的请求。

我错过了什么吗?或者我使用 vertx 错误?


更新1:让繁重的工作回归 future :

@Override
public Future doHeavyJob(String layer) {
    Future future = Future.future();
    new Thread(()->{
        List d = doDataseJob(tile, layer, future);
        d = doCalculationJob(d);
        future.complete(d)
    }).start();
    return future;
}

最佳答案

正如我在另一个主题中已经提到的,您以错误的方式使用 Vert.x。
没有并发增益,因为您所做的正是 servlet 之前所做的事情:在线程池上放置很长的工作。
事实上,使用 EventLoop 来完成这个任务并不会改变任何事情。它甚至可能会变得更糟,因为 Vert.x 工作线程池默认非常小,只有 20 个线程。如果您的 servlet 容器配置了更多线程,实际上,它在该设置中的性能会优于 Vert.x。

你应该做什么:

  • 如果存在独立查询,请并行执行它们,并使用 Future 组合它们的结果
  • 将 DAO 封装在 verticle 中,并使用 EventBus 进行通信

请注意,如果您的查询长达 4 秒,一旦您解决这些问题,您的数据库将成为瓶颈。

关于java - 异步和同步模式的并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50195673/

相关文章:

java - 如何删除包含Java中其他文件夹的文件夹?

python - 地址已在twisted 中与多线程服务器一起使用

java - 使用 Lambda 表达式参数化的 Vert.x 日志语句

java - 以下情况的 hashCode() 方法 : two sets are equal when they have at least one element in common?

java - 使用 jose4j 访问 JWT 嵌套声明

JavaFX ComboBox<POJO> 不更新值

java - 如何使我的Keystore文件与Java Vert.x项目一起使用(无效的Keystore格式)

java - 在java中通过线程显示图像序列

python - python函数如何调用并且不等待它完成处理,而该函数必须被调用一次。因此,线程必须停止

java - Vert.x OutOfMemoryError 工作线程队列