我正在使用Vert.x和相当于基于事件循环的服务器,而不是线程/连接模型.
public void start(Future<Void> fut) {
    vertx
        .createHttpServer()
        .requestHandler(r -> {
            LocalDateTime start = LocalDateTime.Now();
            System.out.println("Request received - "+start.format(DateTimeFormatter.ISO_DATE_TIME));
            final MyModel model = new MyModel();
            try {

                for(int i=0;i<10000000;i++){
                    //some simple operation
                }

                model.data = start.format(DateTimeFormatter.ISO_DATE_TIME) +" - "+LocalDateTime.Now().format(DateTimeFormatter.ISO_DATE_TIME);

            } catch (Exception e1) {
                // Todo Auto-generated catch block
                e1.printstacktrace();
            }

          r.response().end(
                  new Gson().toJson(model)
                 );
        })
        .listen(4568,result -> {
          if (result.succeeded()) {
            fut.complete();
          } else {
            fut.fail(result.cause());
          }
        });
    System.out.println("Server started ..");
  }

>我只是想模拟一个长时间运行的请求处理程序来了解这个模型的工作原理.
>我观察到的是所谓的事件循环被阻塞,直到我的第一个请求完成.无论什么时间需要,后续请求不会被执行,直到前一个完成.
显然,我在这里错过了一件,这就是我在这里的问题.

根据答案编辑到目前为止:

>不接受被认为是异步的所有请求?如果一个新的
只有当前一个清除时才能接受连接
关闭,如何异步?

>假设典型的请求需要100 ms到1 sec之间(根据请求的种类和性质).所以这意味着
事件循环直到先前的请求才能接受新的连接
完成(即使它在一秒钟内风起来).如果我是一个程序员
必须考虑所有这些,并将这些请求处理程序推送到
工作线程,那么它如何与线程/连接有所不同
模型?
>我只是想了解传统线程/连接服务器型号的这个模型是如何更好的?假设没有I / O操作或
所有的I / O操作是异步处理的?它甚至如何解决
c10k问题,当它不能并行启动所有并发请求,并且必须等到上一个终止?

>即使我决定将所有这些操作推送到工作线程(pooled),那么我回到同样的问题呢?上下文切换线程?
编辑并填补这个问题的赏金

>不完全明白这个模型是如何声称异步的.
> Vert.x有一个异步JDBC客户端(Asyncronous是关​​键字),我试图用RXJava进行调整.
>这里是代码示例(相关部分)

server.requestStream().toObservable().subscribe(req – > {

LocalDateTime start = LocalDateTime.Now();
        System.out.println("Request for " + req.absoluteURI() +" received - " +start.format(DateTimeFormatter.ISO_DATE_TIME));
        jdbc.getConnectionObservable().subscribe(
                conn -> {

                    // Now chain some statements using flatmap composition
                    Observable<ResultSet> resa = conn.queryObservable("SELECT * FROM CALL_OPTION WHERE UNDERLYING='NIFTY'");
                    // Subscribe to the final result
                    resa.subscribe(resultSet -> {

                        req.response().end(resultSet.getRows().toString());
                        System.out.println("Request for " + req.absoluteURI() +" Ended - " +LocalDateTime.Now().format(DateTimeFormatter.ISO_DATE_TIME));
                    },err -> {
                        System.out.println("Database problem");
                        err.printstacktrace();
                    });
                },// Could not connect
                err -> {
                    err.printstacktrace();
                }
                );

});
server.listen(4568);

>选择查询需要3秒钟,大约返回完整的表转储.
>当我启动并发请求(仅使用2)时,我看到第二个请求完全等待第一个请求完成.
>如果JDBC select是异步的,在等待select查询返回任何东西的时候,框架是否处理第二个连接是不是一个很好的期望?

解决方法

事实上,Vert.x事件循环是许多平台上存在的经典事件循环.当然,对于Node.js来说,大多数解释和文档都可以找到,因为它是基于这种架构模式的最流行的框架.在Node.js事件循环下,看看一个或多或少的优秀的机械师 explanation. Vert.x tutorial在“不要打电话给我们,我们打电话给你”和“Verticles”也有很好的解释.

编辑您的更新:

首先,当您处理事件循环时,主线程对于所有请求都应该很快地工作.你不应该在这个循环中做任何长工作.当然你也不应该等到你对数据库的回应.
– 异步调度一个调用
– 将回调(处理程序)分配给结果
– 回调将在工作线程,非事件循环线程中执行.例如,此回调将返回对套接字的响应.
所以,你在事件循环中的操作应该只是调用所有异步操作与回调,并转到下一个请求,而不等待任何结果.

Assume a typical request takes anywhere between 100 ms to 1 sec (based on the kind and nature of the request).

在这种情况下,您的请求有一些计算昂贵的部分或访问IO – 您的事件循环中的代码不应该等待此操作的结果.

I’m just trying to understand how is this model better from a Traditional thread/conn server models? Assume there is no I/O op or all the I/O op are handled asynchronously?

当您有太多的并发请求和传统的编程模型时,您将根据每个请求进行线程.这个线程会做什么?他们将主要等待IO操作(例如,数据库的结果).浪费资源在我们的事件循环模型中,您有一个主线程用于计划操作,并为长任务预先分配了工作线程数量.没有一个这个工作人员实际上等待响应,他们只需执行另一个代码,同时等待IO结果(可以实现为当前正在进行的IO作业的回调或定期检查状态).我建议您通过Java NIO和Java NIO 2来了解如何在框架内实际执行此异步IO. Green threads也是非常相关的概念,那将是很好的理解.绿色线程和协同程序是一种阴影事件循环,试图实现相同的事情 – 少线程,因为我们可以重用系统线程,而绿色线程等待某事.

How does it even solve c10k problem,when it can’t start all concurrent requests parallel and have to wait till the prevIoUs one terminates?

确定我们不要等待主线程发送先前请求的响应.获取请求,安排长/ IO任务执行,下次请求.

Even if I decide to push all these operations to a worker thread(pooled),then I’m back to the same problem isn’t it? Context switching between threads?

如果你使一切正确 – 不.更重要的是,您将获得良好的数据位置和执行流预测.一个cpu内核将执行您的短事件循环并调度异步工作,无需上下文切换,而无需再进行任何操作.其他核心调用数据库并返回响应,只有这样.在回调之间切换或检查不同通道的IO状态实际上不需要任何系统线程的上下文切换 – 它实际上在一个工作线程中工作.因此,我们每个核心都有一个工作线程,这个系统线程等待/检查从多个连接到数据库的结果可用性.回顾Java NIO概念,了解它如何以这种方式工作. (NIO代理服务器的典型示例 – 可以接受多个并行连接(数千个)的代理服务器,向其他一些远程服务器发送代理请求,收听响应并将响应发送回客户端,所有这些使用一个或两个线程)

关于你的代码,我为你做了一个样例project来证明一切都符合预期:

public class MyFirstVerticle extends AbstractVerticle {

    @Override
    public void start(Future<Void> fut) {
        JDBcclient client = JDBcclient.createShared(vertx,new JsonObject()
                .put("url","jdbc:hsqldb:mem:test?shutdown=true")
                .put("driver_class","org.hsqldb.jdbcDriver")
                .put("max_pool_size",30));


        client.getConnection(conn -> {
            if (conn.Failed()) {throw new RuntimeException(conn.cause());}
            final sqlConnection connection = conn.result();

            // create a table
            connection.execute("create table test(id int primary key,name varchar(255))",create -> {
                if (create.Failed()) {throw new RuntimeException(create.cause());}
            });
        });

        vertx
            .createHttpServer()
            .requestHandler(r -> {
                int requestId = new Random().nextInt();
                System.out.println("Request " + requestId + " received");
                    client.getConnection(conn -> {
                         if (conn.Failed()) {throw new RuntimeException(conn.cause());}

                         final sqlConnection connection = conn.result();

                         connection.execute("insert into test values ('" + requestId + "','World')",insert -> {
                             // query some data with arguments
                             connection
                                 .queryWithParams("select * from test where id = ?",new JsonArray().add(requestId),rs -> {
                                     connection.close(done -> {if (done.Failed()) {throw new RuntimeException(done.cause());}});
                                     System.out.println("Result " + requestId + " returned");
                                     r.response().end("Hello");
                                 });
                         });
                     });
            })
            .listen(8080,result -> {
                if (result.succeeded()) {
                    fut.complete();
                } else {
                    fut.fail(result.cause());
                }
            });
    }
}

@RunWith(VertxUnitRunner.class)
public class MyFirstVerticleTest {

  private Vertx vertx;

  @Before
  public void setUp(TestContext context) {
    vertx = Vertx.vertx();
    vertx.deployVerticle(MyFirstVerticle.class.getName(),context.asyncAssertSuccess());
  }

  @After
  public void tearDown(TestContext context) {
    vertx.close(context.asyncAssertSuccess());
  }

  @Test
  public void testMyApplication(TestContext context) {
      for (int i = 0; i < 10; i++) {
          final Async async = context.async();
          vertx.createHttpClient().getNow(8080,"localhost","/",response -> response.handler(body -> {
                                context.assertTrue(body.toString().contains("Hello"));
                                async.complete();
                            })
        );
    }
  }
}

输出:

Request 1412761034 received
Request -1781489277 received
Request 1008255692 received
Request -853002509 received
Request -919489429 received
Request 1902219940 received
Request -2141153291 received
Request 1144684415 received
Request -1409053630 received
Request -546435082 received
Result 1412761034 returned
Result -1781489277 returned
Result 1008255692 returned
Result -853002509 returned
Result -919489429 returned
Result 1902219940 returned
Result -2141153291 returned
Result 1144684415 returned
Result -1409053630 returned
Result -546435082 returned

所以,我们接受请求 – 调度请求到数据库,去下一个请求,我们消耗所有它们,并发送每个请求的响应只有当所有的数据库完成.

关于你的代码示例我看到两个可能的问题 – 首先,看起来你不关闭()连接,这是重要的返回到池.二,池如何配置?如果只有一个免费连接 – 这个请求将序列化等待这个连接.

我建议您添加一些打印时间戳的两个请求,以查找序列化的位置.你把一些让事件循环阻塞的调用.或者…检查您在测试中并发发送请求.以前没有得到响应之后.

java – Vert.x事件循环 – 这是怎么异步的?的更多相关文章

  1. iOS:核心图像和多线程应用程序

    我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看Apple的核心图像编程指南.关于多线程,它说:“每个线程必须创建自己的CIFilter对象.否则,你的应用程序可能会出现意外行为.”这是什么意思?我实际上是试图在后台线程上运行我的过滤器,所以我可以在主线程上运行HUD(见下文).这在coreImage的上下文中是否有意义?

  2. ios – 多个NSPersistentStoreCoordinator实例可以连接到同一个底层SQLite持久性存储吗?

    我读过的关于在多个线程上使用CoreData的所有内容都讨论了使用共享单个NSPersistentStoreCoordinator的多个NSManagedobjectContext实例.这是理解的,我已经使它在一个应用程序中工作,该应用程序在主线程上使用CoreData来支持UI,并且具有可能需要一段时间才能运行的后台获取操作.问题是NSPersistentStoreCoordinator会对基础

  3. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  4. ios – 在后台线程中写入Realm后,主线程看不到更新的数据

    >清除数据库.>进行API调用以获取新数据.>将从API检索到的数据写入后台线程中的数据库中.>从主线程上的数据库中读取数据并渲染UI.在步骤4中,数据应该是最新数据,但我们没有看到任何数据.解决方法具有runloops的线程上的Realm实例,例如主线程,updatetothelatestversionofthedataintheRealmfile,因为通知被发布到其线程的runloop.在后台

  5. ios – NSURLConnectionLoader线程中的奇怪崩溃

    我们开始看到我们的应用启动时发生的崩溃.我无法重现它,它只发生在少数用户身上.例外情况是:异常类型:EXC_BAD_ACCESS代码:KERN_INVALID_ADDRESS位于0x3250974659崩溃发生在名为com.apple.NSURLConnectionLoader的线程中在调用时–[NSBlockOperationmain]这是该线程的堆栈跟踪:非常感谢任何帮助,以了解可能导致这种崩

  6. ios – 合并子上下文时的NSObjectInaccessbileExceptions

    我尝试手动重现,但失败了.是否有其他可能发生这种情况的情况,是否有处理此类问题的提示?解决方法在创建子上下文时,您可以尝试使用以下行:

  7. ios – 从后台线程调用UIKit时发出警告

    你如何处理项目中的这个问题?

  8. ios – 在SpriteKit中,touchesBegan在与SKScene更新方法相同的线程中运行吗?

    在这里的Apple文档AdvancedSceneProcessing中,它描述了更新方法以及场景的呈现方式,但没有提到何时处理输入.目前尚不清楚它是否与渲染循环位于同一个线程中,或者它是否与它并发.如果我有一个对象,我从SKScene更新方法和touchesBegan方法(在这种情况下是SKSpriteNode)更新,我是否要担心同步对我的对象的两次访问?解决方法所以几天后没有回答我设置了一些实验

  9. ios – 在后台获取中加载UIWebView

    )那么,有一种方法可以在后台加载UIWebView吗?解决方法如果要从用户界面更新元素,则必须在应用程序的主队列(或线程)中访问它们.我建议您在后台继续获取所需的数据,但是当需要更新UIWebView时,请在主线程中进行.你可以这样做:或者您可以创建一个方法来更新UIWebView上的数据,并使用以下方法从后台线程调用它:这将确保您从正确的线程访问UIWebView.希望这可以帮助.

  10. ios – 何时使用Semaphore而不是Dispatch Group?

    我会假设我知道如何使用DispatchGroup,为了解问题,我尝试过:结果–预期–是:为了使用信号量,我实现了:并在viewDidLoad方法中调用它.结果是:从概念上讲,dispachGroup和Semaphore都有同样的目的.老实说,我不熟悉:什么时候使用信号量,尤其是在与dispachGroup合作时–可能–处理问题.我错过了什么部分?

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部