工作者Verticle没有并行处理请求

时间:2016-09-25 15:18:19

标签: multithreading concurrency vert.x

我正在尝试扩展一个对外部应用程序执行阻塞调用以获取某些数据的应用程序(请求和响应顺序无关紧要)

因为,它在vertx docs中描述了一个阻塞调用,我正在使用worker worker,worker worker设置为5,并且我已经部署了5个worker verticle实例

当我提交多个查询时(当我测试时我刚刚解雇了3个查询),即使我的Verticle被定义为具有多个具有足够工作线程并且并行处理我的请求的实例的worker,它们也不会同时处理,看起来它们是按顺序处理的(见下面的日志)

我还尝试创建一个主Verticle和4个worker verticle(句柄阻塞调用),其中来自客户端的初始请求在主Verticle上接收,master通过事件总线将请求发送给worker并且它响应但是甚至这个方式我看到与上面解释的相同的行为

请建议我是否误解了某些内容以及是否尝试以不正确的方式实现并发。如果是这样,请建议实现此用例并发性的最佳方法

VertxMain.java

public class VertxMain  {
public static final Logger LOG =Logger.getLogger(VertxMain.class.getName());
public static void main(String[] args) {      
MyFirstVerticle mfv = new MyFirstVerticle();
DeploymentOptions deploymentOptions = new DeploymentOptions().setWorker(true).setInstances(5);
  Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(5));
  vertx.deployVerticle(MyFirstVerticle.class.getName(), deploymentOptions, res ->{
      if(res.succeeded()) {
          LOG.info("first verticle deployed");
      } else{
          LOG.info("first verticle failed to deployed" + res.cause());
      }
  });

MyFirstVerticle.java

public class MyFirstVerticle extends AbstractVerticle {
public static final Logger LOG = Logger.getLogger(MyFirstVerticle.class.getName()); 
Integer requestCount = 0;

@Override
public void start(Future<Void> fut) {
    InputStream is = this.getClass().getClassLoader().getResourceAsStream("qa.properties");
    Scanner sc = new Scanner(is);
    String line = sc.nextLine();

    Router router = Router.router(vertx);

    router.route("/qa").handler(routingContext -> {
         requestCount++;
        Date d = new Date();

         System.out.println("Received request #" + requestCount.toString() + " on " +d.toString());
         try {
                LOG.info("Processing request");
                Thread.sleep(20000);
                d.setTime(System.currentTimeMillis());
                System.out.println("Responding to request #" + requestCount.toString() + " on " +d.toString());
            } catch (Exception e) {
            }

        routingContext.response().end("<h1>Hello from my first " + 
                " Vert.x 3 application using " + Thread.currentThread().getName() + line + "</h1>");
    });

    vertx
    .createHttpServer()
    .requestHandler(router::accept)
    .listen(8081, result -> {
        if (result.succeeded()) {
            LOG.info("Webserver started to serve requests!!");
            fut.complete();
        } else {
            fut.fail(result.cause());
        }
    });
}

日志:

INFO: first verticle deployed
Received request #1 on Sun Sep 25 11:06:10 EDT 2016
Sep 25, 2016 11:06:10 AM com.myvertx.MyFirstVerticle lambda$0
INFO: Processing request
Responding to request #1 on Sun Sep 25 11:06:30 EDT 2016
Received request #2 on Sun Sep 25 11:06:30 EDT 2016
Sep 25, 2016 11:06:30 AM com.myvertx.MyFirstVerticle lambda$0
INFO: Processing request
Received request #1 on Sun Sep 25 11:06:36 EDT 2016 ->( *Looks like request is routed to a different instance of the verticle* )
Sep 25, 2016 11:06:36 AM com.myvertx.MyFirstVerticle lambda$0
INFO: Processing request
Responding to request #2 on Sun Sep 25 11:06:50 EDT 2016
Responding to request #1 on Sun Sep 25 11:06:56 EDT 2016

2 个答案:

答案 0 :(得分:3)

在vertx中,正常的Verticle与事件循环相关联。所以对该Verticle的任何请求都必须等到事件循环变为空闲;即使没有同一个Verticle的其他实例正在运行。通过允许Verticle在任何工作线程中运行,工作者Verticle放松了这一点,但是工作者Verticle的实例不能同时处理两个请求。为了更进一步,您可以使用多线程工作者Verticle,它可以同时执行多个请求。

因此,要回答您的问题,您可以创建多个工作者Verticle实例,也可以创建多线程工作者Verticle。

您可以在http://vertx.io/docs/vertx-core/java/#_verticle_types

找到更多信息

答案 1 :(得分:2)

问题部分在于我的测试方法 - 我发出了来自不同浏览器标签的多个请求。正如上面的日志说的那样顺序处理它(我还没找到答案为什么)因此我写了一个简单的异步客户端并同时发出多个请求,这些请求是从不同的工作者Verticle并行处理的

我对我的测试进行了跟踪,我认为我说得太早,因此发布了我的发现